<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<link href="common/css/sf.css" rel="stylesheet" type="text/css"/>
<title>Hoare: 霍尔逻辑（第一部分）</title>
</head>
<link href="common/jquery-ui/jquery-ui.css" rel="stylesheet">
<script src="common/jquery-ui/external/jquery/jquery.js"></script>
<script src="common/jquery-ui/jquery-ui.js"></script>
<script src="common/toggleproofs.js"></script>
<link href="common/css/plf.css" rel="stylesheet" type="text/css"/>

<body>

<div id="page">

<div id="header">
<a href='https://coq-zh.github.io/SF-zh/index.html'>
<img src='common/media/image/sf_logo_sm.png'></a>
</br><a href='index.html'>  <span class='booktitleinheader'>Volume 2: 编程语言基础</span><br></br>
<ul id='menu'>
   <a href='toc.html'><li class='section_name'>目录</li></a>
   <a href='coqindex.html'><li class='section_name'>索引</li></a>
   <a href='deps.html'><li class='section_name'>路线</li></a>
</ul>
</a></div>

<div id="main">

<h1 class="libtitle">Hoare<span class="subtitle">霍尔逻辑（第一部分）</span></h1>


<div class="code code-tight">

<span class="id" type="keyword">Set</span> <span class="id" type="var">Warnings</span> "-notation-overridden,-parsing".<br/>
<span class="id" type="var">From</span> <span class="id" type="var">PLF</span> <span class="id" type="keyword">Require</span> <span class="id" type="keyword">Import</span> <span class="id" type="var">Maps</span>.<br/>
<span class="id" type="var">From</span> <span class="id" type="var">Coq</span> <span class="id" type="keyword">Require</span> <span class="id" type="keyword">Import</span> <span class="id" type="var">Bool.Bool</span>.<br/>
<span class="id" type="var">From</span> <span class="id" type="var">Coq</span> <span class="id" type="keyword">Require</span> <span class="id" type="keyword">Import</span> <span class="id" type="var">Arith.Arith</span>.<br/>
<span class="id" type="var">From</span> <span class="id" type="var">Coq</span> <span class="id" type="keyword">Require</span> <span class="id" type="keyword">Import</span> <span class="id" type="var">Arith.EqNat</span>.<br/>
<span class="id" type="var">From</span> <span class="id" type="var">Coq</span> <span class="id" type="keyword">Require</span> <span class="id" type="keyword">Import</span> <span class="id" type="var">Arith.PeanoNat</span>. <span class="id" type="keyword">Import</span> <span class="id" type="var">Nat</span>.<br/>
<span class="id" type="var">From</span> <span class="id" type="var">Coq</span> <span class="id" type="keyword">Require</span> <span class="id" type="keyword">Import</span> <span class="id" type="var">omega.Omega</span>.<br/>
<span class="id" type="var">From</span> <span class="id" type="var">PLF</span> <span class="id" type="keyword">Require</span> <span class="id" type="keyword">Import</span> <span class="id" type="var">Imp</span>.<br/>
</div>

<div class="doc">
在<b>逻辑基础</b>（<b>软件基础</b> 的第一章) 中，
    我们用课程前面的部分中学习的数学工具研究了一个小型编程语言 Imp 。

<div class="paragraph"> </div>

<ul class="doclist">
<li> 我们给 Imp 定义了<b>抽象语法树（abstract syntax trees）</b>；
      还有<b>求值关系（evaluation relation）</b>（一个在状态上的偏函数），
      它给出了程序的<b>操作语义（operational semantics）</b>。

<div class="paragraph"> </div>

      我们定义的这个小型语言实现了一些完善语言（例如 C、C++ 和 Java）
      的关键功能，包括基础的可变状态和控制流的概念。

<div class="paragraph"> </div>


</li>
<li> 我们证明了许多<b>元理论性质（metatheoretic properties）</b>，也就是
      从高层次角度来说，这些性质是关于这整个语言的，而不是关于任何一段
      单独的程序。这包括了：

<div class="paragraph"> </div>

<ul class="doclist">
<li> 求值过程的确定性

<div class="paragraph"> </div>


</li>
<li> 用不同方式写下的定义之等价关系（例如，用求值函数和求值关系来定
          义算术表达式的化简规则）

<div class="paragraph"> </div>


</li>
<li> 保证一系列程序必会停机

<div class="paragraph"> </div>


</li>
<li> 数个实用的程序变换之正确性（从语义等价的角度来讲）

<div class="paragraph"> </div>


</li>
<li> 程序的等价关系（在 <a href="Equiv.html"><span class="inlineref">Equiv</span></a> 这一章里）。 
</li>
</ul>

</li>
</ul>

<div class="paragraph"> </div>

 如果在这里打住，我们已经有了一些实用的东西了：一套用来定义并讨论
    程序语言和它们的功能的工具。这些工具应用于程序语言的一些关键性质，
    （从数学角度来讲）是严谨和灵活的，并且是易于使用的。
    所有这些性质都是程序语言的设计者，编译器作者，以及用户所最关心的。
    当然，这些性质中的很多是极为基础的，以至于在我们对编程语言的认知
    中甚至不会把它们自然地当做“定理”来对待。但看似直观明显的属性有时候
    可能会非常微妙（有时也会错得很微妙！）。

<div class="paragraph"> </div>

    在这一卷稍后，我们将会在讨论<b>类型（types）</b>和<b>类型可靠性
    （type soundness）</b>时，回归到整个语言的元理论性质研究。不过现在
    我们要着眼于另外一些问题。

<div class="paragraph"> </div>

    我们的目标是给出一些<b>软件形式化验证（program verification）</b>
    的例子，也就是说，用 Imp 的精确定义来形式地证明某段程序符合某
    个规范。我们会建立一个叫做<b>弗洛伊德-霍尔逻辑（Floyd-Hoare Logic）</b>
    的系统（一般简称 <b>霍尔逻辑（Hoare Logic）</b>），它是 Imp 的语法构造
    加上了一个通用的“验证规则”的组合，可以用来说明包含这段结构的程序
    之正确性。

<div class="paragraph"> </div>

    霍尔逻辑发源于1960年代，至今为止依然是活跃的研究主题。
    它用于规范和验证许多学术界与工业界广泛使用的软件系统，并处于核心地位。

<div class="paragraph"> </div>

    霍尔逻辑组合了两个绝妙的想法：用自然的方式来编写程序的<b>规范（specifications）</b>
    ；和一种用来证明程序正确地实现了规范的<b>复合证明技巧（compositional proof technique）</b>
    ——其中“复合”的意思是，这些证明的结构直接反映了相应程序的结构。
<div class="paragraph"> </div>

 本章概览...
    主题：

<div class="paragraph"> </div>

<ul class="doclist">
<li> 推理 Imp 程序<b>功能正确性（functional correctness）</b> 的系统方法

</li>
</ul>

<div class="paragraph"> </div>

    目标：

<div class="paragraph"> </div>

<ul class="doclist">
<li> 一种自然表达<b>程序规范（program specifications）</b>的记号

</li>
<li> 一种关于程序正确性的<b>复合的（compositional）</b>证明技巧

</li>
</ul>

<div class="paragraph"> </div>

    计划：

<div class="paragraph"> </div>

<ul class="doclist">
<li> 程序规范（断言／霍尔三元组）

</li>
<li> 证明规则

</li>
<li> 循环不变式

</li>
<li> 带标注的程序

</li>
<li> 例子 
</li>
</ul>

</div>

<div class="doc">
<a name="lab49"></a><h1 class="section">断言</h1>

<div class="paragraph"> </div>

 要讨论程序的规范，我们需要的首先是一种在程序执行过程中某个时刻，
    关于程序性质做出<b>断言（assertions）</b>的方法。也就是说，我们要讨论执
    行到某处时，当时的内存状态。形式化地说，一项断言就是一系列关于 <span class="inlinecode"><span class="id" type="var">state</span></span>
    的命题。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Definition</span> <span class="id" type="var">Assertion</span> := <span class="id" type="var">state</span> → <span class="id" type="keyword">Prop</span>.<br/>
</div>

<div class="doc">
<a name="lab50"></a><h4 class="section">练习：1 星, standard, optional (assertions)</h4>
 用中文重新表述下列断言（或者用你最喜欢的语言）。 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Module</span> <span class="id" type="var">ExAssertions</span>.<br/>
<span class="id" type="keyword">Definition</span> <span class="id" type="var">as<sub>1</sub></span> : <span class="id" type="var">Assertion</span> := <span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">st</span> <span class="id" type="var">X</span> = 3.<br/>
<span class="id" type="keyword">Definition</span> <span class="id" type="var">as<sub>2</sub></span> : <span class="id" type="var">Assertion</span> := <span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">st</span> <span class="id" type="var">X</span> ≤ <span class="id" type="var">st</span> <span class="id" type="var">Y</span>.<br/>
<span class="id" type="keyword">Definition</span> <span class="id" type="var">as<sub>3</sub></span> : <span class="id" type="var">Assertion</span> :=<br/>
&nbsp;&nbsp;<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">st</span> <span class="id" type="var">X</span> = 3 ∨ <span class="id" type="var">st</span> <span class="id" type="var">X</span> ≤ <span class="id" type="var">st</span> <span class="id" type="var">Y</span>.<br/>
<span class="id" type="keyword">Definition</span> <span class="id" type="var">as<sub>4</sub></span> : <span class="id" type="var">Assertion</span> :=<br/>
&nbsp;&nbsp;<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">st</span> <span class="id" type="var">Z</span> * <span class="id" type="var">st</span> <span class="id" type="var">Z</span> ≤ <span class="id" type="var">st</span> <span class="id" type="var">X</span> ∧<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;¬(((<span class="id" type="var">S</span> (<span class="id" type="var">st</span> <span class="id" type="var">Z</span>)) * (<span class="id" type="var">S</span> (<span class="id" type="var">st</span> <span class="id" type="var">Z</span>))) ≤ <span class="id" type="var">st</span> <span class="id" type="var">X</span>).<br/>
<span class="id" type="keyword">Definition</span> <span class="id" type="var">as<sub>5</sub></span> : <span class="id" type="var">Assertion</span> := <span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">True</span>.<br/>
<span class="id" type="keyword">Definition</span> <span class="id" type="var">as<sub>6</sub></span> : <span class="id" type="var">Assertion</span> := <span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">False</span>.<br/>
<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span><br/>
<span class="id" type="keyword">End</span> <span class="id" type="var">ExAssertions</span>.<br/>
</div>

<span class="proofbox">&#9744;</span> 
<div class="doc less-space">
<div class="paragraph"> </div>

 这种写下断言的方式可能过于繁琐，理由如下：
    (1) 我们写的每个断言都将以 <span class="inlinecode"><span class="id" type="keyword">fun</span></span> <span class="inlinecode"><span class="id" type="var">st</span></span> <span class="inlinecode">⇒</span> <span class="inlinecode"></span> 开头；
    (2) 状态 <span class="inlinecode"><span class="id" type="var">st</span></span> 是唯一我们希望用来再断言中查找变量的状态（我们将不会
    讨论在同一时间的两种不同状态。
    当我们非正式地讨论某些例子的时候，我们会简化一下：我们把开头的
    <span class="inlinecode"><span class="id" type="keyword">fun</span></span> <span class="inlinecode"><span class="id" type="var">st</span></span> <span class="inlinecode">⇒</span> 去掉，并且用 <span class="inlinecode"><span class="id" type="var">X</span></span> 来代替 <span class="inlinecode"><span class="id" type="var">st</span></span> <span class="inlinecode"><span class="id" type="var">X</span></span> 所以，我们将把
<div class="paragraph"> </div>


<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">fun</span>&nbsp;<span class="id" type="var">st</span>&nbsp;⇒&nbsp;(<span class="id" type="var">st</span>&nbsp;<span class="id" type="var">Z</span>)&nbsp;*&nbsp;(<span class="id" type="var">st</span>&nbsp;<span class="id" type="var">Z</span>)&nbsp;≤&nbsp;<span class="id" type="var">m</span>&nbsp;∧<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;¬((<span class="id" type="var">S</span>&nbsp;(<span class="id" type="var">st</span>&nbsp;<span class="id" type="var">Z</span>))&nbsp;*&nbsp;(<span class="id" type="var">S</span>&nbsp;(<span class="id" type="var">st</span>&nbsp;<span class="id" type="var">Z</span>))&nbsp;≤&nbsp;<span class="id" type="var">m</span>)
<div class="paragraph"> </div>

</div>
    写成

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Z</span>&nbsp;*&nbsp;<span class="id" type="var">Z</span>&nbsp;≤&nbsp;<span class="id" type="var">m</span>&nbsp;∧&nbsp;~((<span class="id" type="var">S</span>&nbsp;<span class="id" type="var">Z</span>)&nbsp;*&nbsp;(<span class="id" type="var">S</span>&nbsp;<span class="id" type="var">Z</span>)&nbsp;≤&nbsp;<span class="id" type="var">m</span>).
<div class="paragraph"> </div>

</div>

<div class="paragraph"> </div>

 这个例子也同时展示了我们将使用的另一种简便写法，我们将
    在关于霍尔逻辑的章节里都使用它：在非正式的断言中，大写字母例如 <span class="inlinecode"><span class="id" type="var">X</span></span>、
    <span class="inlinecode"><span class="id" type="var">Y</span></span>、<span class="inlinecode"><span class="id" type="var">Z</span></span> 是 Imp 变量，而小写字母例如 <span class="inlinecode"><span class="id" type="var">x</span></span>、<span class="inlinecode"><span class="id" type="var">y</span></span>、<span class="inlinecode"><span class="id" type="var">m</span></span>、<span class="inlinecode"><span class="id" type="var">n</span></span> 则是一般的 Coq
    变量（类型是 <span class="inlinecode"><span class="id" type="var">nat</span></span>）。这就是当我们把非正式断言翻译成正式断言时，把
    <span class="inlinecode"><span class="id" type="var">X</span></span> 换成 <span class="inlinecode"><span class="id" type="var">st</span></span> <span class="inlinecode"><span class="id" type="var">X</span></span> 而留下 <span class="inlinecode"><span class="id" type="var">m</span></span> 不变的理由。
<div class="paragraph"> </div>

 给出两断言 <span class="inlinecode"><span class="id" type="var">P</span></span> 与 <span class="inlinecode"><span class="id" type="var">Q</span></span>，我们说 <span class="inlinecode"><span class="id" type="var">P</span></span> <b>蕴含</b> <span class="inlinecode"><span class="id" type="var">Q</span></span>，
    写作 <span class="inlinecode"><span class="id" type="var">P</span></span> <span class="inlinecode"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>></span>></span></span></span> <span class="inlinecode"><span class="id" type="var">Q</span></span>，如果当 <span class="inlinecode"><span class="id" type="var">P</span></span> 在 <span class="inlinecode"><span class="id" type="var">st</span></span> 下成立，<span class="inlinecode"><span class="id" type="var">Q</span></span> 也成立。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Definition</span> <span class="id" type="var">assert_implies</span> (<span class="id" type="var">P</span> <span class="id" type="var">Q</span> : <span class="id" type="var">Assertion</span>) : <span class="id" type="keyword">Prop</span> :=<br/>
&nbsp;&nbsp;<span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span>, <span class="id" type="var">P</span> <span class="id" type="var">st</span> → <span class="id" type="var">Q</span> <span class="id" type="var">st</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Notation</span> "P <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>></span>></span></span> Q" := (<span class="id" type="var">assert_implies</span> <span class="id" type="var">P</span> <span class="id" type="var">Q</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 80) : <span class="id" type="var">hoare_spec_scope</span>.<br/>
<span class="id" type="keyword">Open</span> <span class="id" type="keyword">Scope</span> <span class="id" type="var">hoare_spec_scope</span>.<br/>
</div>

<div class="doc">
这里的记号 <span class="inlinecode"><span class="id" type="var">hoare_spec_scope</span></span> 告诉 Coq， 这个记号不是全局的，
    我们打算把它用在特定的上下文里。<span class="inlinecode"><span class="id" type="keyword">Open</span></span> <span class="inlinecode"><span class="id" type="keyword">Scope</span></span> 告诉 Coq，这个文件就是
    一个我们将采用此记号的上下文。 
<div class="paragraph"> </div>

 我们也需要一个表达断言之间“当且仅当”的蕴含关系：
</div>
<div class="code code-tight">

<span class="id" type="keyword">Notation</span> "P <span class="nowrap"><span style='font-size:85%;'><span style='letter-spacing:-.2em;'><<</span><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>></span>></span></span> Q" :=<br/>
&nbsp;&nbsp;(<span class="id" type="var">P</span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>></span>></span></span> <span class="id" type="var">Q</span> ∧ <span class="id" type="var">Q</span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>></span>></span></span> <span class="id" type="var">P</span>) (<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 80) : <span class="id" type="var">hoare_spec_scope</span>.<br/>
</div>

<div class="doc">
<a name="lab51"></a><h1 class="section">霍尔三元组</h1>

<div class="paragraph"> </div>

 接下来，我们需要一种描述命令行为的方式。
<div class="paragraph"> </div>

 广泛而言，一个命令的行为就是把一个状态转变成另一个状态，所以
    我们可以自然地通过命令运行前后的断言来描述一个命令。

<div class="paragraph"> </div>

<ul class="doclist">
<li> “如果命令 <span class="inlinecode"><span class="id" type="var">c</span></span> 在一个复合断言 <span class="inlinecode"><span class="id" type="var">P</span></span> 的状态开始，并且如果 <span class="inlinecode"><span class="id" type="var">c</span></span>
        最终在一个结束状态停机，这个结束状态会满足断言 <span class="inlinecode"><span class="id" type="var">Q</span></span>。”

</li>
</ul>

<div class="paragraph"> </div>

    这样的描述叫做<b>霍尔三元组（Hoare Triple）</b>。断言 <span class="inlinecode"><span class="id" type="var">P</span></span> 叫做 <span class="inlinecode"><span class="id" type="var">c</span></span>
    的<b>前置条件（precondition）</b>，而 <span class="inlinecode"><span class="id" type="var">Q</span></span> 叫做 <b>后置条件（postcondition）</b>。
<div class="paragraph"> </div>

 形式化地： 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Definition</span> <span class="id" type="var">hoare_triple</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">P</span> : <span class="id" type="var">Assertion</span>) (<span class="id" type="var">c</span> : <span class="id" type="var">com</span>) (<span class="id" type="var">Q</span> : <span class="id" type="var">Assertion</span>) : <span class="id" type="keyword">Prop</span> :=<br/>
&nbsp;&nbsp;<span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">st'</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">c</span> ]⇒ <span class="id" type="var">st'</span>  →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">P</span> <span class="id" type="var">st</span>  →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Q</span> <span class="id" type="var">st'</span>.<br/>
</div>

<div class="doc">
因为我们将会在霍尔三元组上做很多研究，所以一个紧凑的记号是非常便
    利的：

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>}&nbsp;<span class="id" type="var">c</span>&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Q</span><span style='letter-spacing:-.4em;'>}</span>}.
<div class="paragraph"> </div>

</div>
 （传统的记号是 <span class="inlinecode">{<span class="id" type="var">P</span>}</span> <span class="inlinecode"><span class="id" type="var">c</span></span> <span class="inlinecode">{<span class="id" type="var">Q</span>}</span>，不过单花括号已经被用在 Coq 中其
    它东西上了。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Notation</span> "<span style='letter-spacing:-.4em;'>{</span>{ P <span style='letter-spacing:-.4em;'>}</span>}  c  <span style='letter-spacing:-.4em;'>{</span>{ Q <span style='letter-spacing:-.4em;'>}</span>}" :=<br/>
&nbsp;&nbsp;(<span class="id" type="var">hoare_triple</span> <span class="id" type="var">P</span> <span class="id" type="var">c</span> <span class="id" type="var">Q</span>) (<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 90, <span class="id" type="var">c</span> <span class="id" type="tactic">at</span> <span class="id" type="var">next</span> <span class="id" type="var">level</span>)<br/>
&nbsp;&nbsp;: <span class="id" type="var">hoare_spec_scope</span>.<br/>
</div>

<div class="doc">
<a name="lab52"></a><h4 class="section">练习：1 星, standard, optional (triples)</h4>
 用中文重新表述下列霍尔三元组。

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;1)&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">True</span><span style='letter-spacing:-.4em;'>}</span>}&nbsp;<span class="id" type="var">c</span>&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">X</span>&nbsp;=&nbsp;5<span style='letter-spacing:-.4em;'>}</span>}<br/>
<br/>
&nbsp;&nbsp;&nbsp;2)&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">X</span>&nbsp;=&nbsp;<span class="id" type="var">m</span><span style='letter-spacing:-.4em;'>}</span>}&nbsp;<span class="id" type="var">c</span>&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">X</span>&nbsp;=&nbsp;<span class="id" type="var">m</span>&nbsp;+&nbsp;5)<span style='letter-spacing:-.4em;'>}</span>}<br/>
<br/>
&nbsp;&nbsp;&nbsp;3)&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">X</span>&nbsp;≤&nbsp;<span class="id" type="var">Y</span><span style='letter-spacing:-.4em;'>}</span>}&nbsp;<span class="id" type="var">c</span>&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Y</span>&nbsp;≤&nbsp;<span class="id" type="var">X</span><span style='letter-spacing:-.4em;'>}</span>}<br/>
<br/>
&nbsp;&nbsp;&nbsp;4)&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">True</span><span style='letter-spacing:-.4em;'>}</span>}&nbsp;<span class="id" type="var">c</span>&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">False</span><span style='letter-spacing:-.4em;'>}</span>}<br/>
<br/>
&nbsp;&nbsp;&nbsp;5)&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">X</span>&nbsp;=&nbsp;<span class="id" type="var">m</span><span style='letter-spacing:-.4em;'>}</span>}<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">c</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Y</span>&nbsp;=&nbsp;<span class="id" type="var">real_fact</span>&nbsp;<span class="id" type="var">m</span><span style='letter-spacing:-.4em;'>}</span>}<br/>
<br/>
&nbsp;&nbsp;&nbsp;6)&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">X</span>&nbsp;=&nbsp;<span class="id" type="var">m</span><span style='letter-spacing:-.4em;'>}</span>}<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">c</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{(<span class="id" type="var">Z</span>&nbsp;*&nbsp;<span class="id" type="var">Z</span>)&nbsp;≤&nbsp;<span class="id" type="var">m</span>&nbsp;∧&nbsp;¬(((<span class="id" type="var">S</span>&nbsp;<span class="id" type="var">Z</span>)&nbsp;*&nbsp;(<span class="id" type="var">S</span>&nbsp;<span class="id" type="var">Z</span>))&nbsp;≤&nbsp;<span class="id" type="var">m</span>)<span style='letter-spacing:-.4em;'>}</span>}
<div class="paragraph"> </div>

</div>

</div>
<div class="code code-tight">
<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span><br/>
</div>

<span class="proofbox">&#9744;</span> 
<div class="doc less-space">
<div class="paragraph"> </div>

<a name="lab53"></a><h4 class="section">练习：1 星, standard, optional (valid_triples)</h4>
 下列的霍尔三元组是否<b>有效</b>，亦即，表述的 <span class="inlinecode"><span class="id" type="var">P</span></span>、<span class="inlinecode"><span class="id" type="var">c</span></span>、<span class="inlinecode"><span class="id" type="var">Q</span></span> 之间的
    关系是否为真？

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;1)&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">True</span><span style='letter-spacing:-.4em;'>}</span>}&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;5&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">X</span>&nbsp;=&nbsp;5<span style='letter-spacing:-.4em;'>}</span>}<br/>
<br/>
&nbsp;&nbsp;&nbsp;2)&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">X</span>&nbsp;=&nbsp;2<span style='letter-spacing:-.4em;'>}</span>}&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;<span class="id" type="var">X</span>&nbsp;+&nbsp;1&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">X</span>&nbsp;=&nbsp;3<span style='letter-spacing:-.4em;'>}</span>}<br/>
<br/>
&nbsp;&nbsp;&nbsp;3)&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">True</span><span style='letter-spacing:-.4em;'>}</span>}&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;5;;&nbsp;<span class="id" type="var">Y</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;0&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">X</span>&nbsp;=&nbsp;5<span style='letter-spacing:-.4em;'>}</span>}<br/>
<br/>
&nbsp;&nbsp;&nbsp;4)&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">X</span>&nbsp;=&nbsp;2&nbsp;∧&nbsp;<span class="id" type="var">X</span>&nbsp;=&nbsp;3<span style='letter-spacing:-.4em;'>}</span>}&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;5&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">X</span>&nbsp;=&nbsp;0<span style='letter-spacing:-.4em;'>}</span>}<br/>
<br/>
&nbsp;&nbsp;&nbsp;5)&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">True</span><span style='letter-spacing:-.4em;'>}</span>}&nbsp;<span class="id" type="var">SKIP</span>&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">False</span><span style='letter-spacing:-.4em;'>}</span>}<br/>
<br/>
&nbsp;&nbsp;&nbsp;6)&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">False</span><span style='letter-spacing:-.4em;'>}</span>}&nbsp;<span class="id" type="var">SKIP</span>&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">True</span><span style='letter-spacing:-.4em;'>}</span>}<br/>
<br/>
&nbsp;&nbsp;&nbsp;7)&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">True</span><span style='letter-spacing:-.4em;'>}</span>}&nbsp;<span class="id" type="var">WHILE</span>&nbsp;<span class="id" type="var">true</span>&nbsp;<span class="id" type="var">DO</span>&nbsp;<span class="id" type="var">SKIP</span>&nbsp;<span class="id" type="var">END</span>&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">False</span><span style='letter-spacing:-.4em;'>}</span>}<br/>
<br/>
&nbsp;&nbsp;&nbsp;8)&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">X</span>&nbsp;=&nbsp;0<span style='letter-spacing:-.4em;'>}</span>}<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">WHILE</span>&nbsp;<span class="id" type="var">X</span>&nbsp;=&nbsp;0&nbsp;<span class="id" type="var">DO</span>&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;<span class="id" type="var">X</span>&nbsp;+&nbsp;1&nbsp;<span class="id" type="var">END</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">X</span>&nbsp;=&nbsp;1<span style='letter-spacing:-.4em;'>}</span>}<br/>
<br/>
&nbsp;&nbsp;&nbsp;9)&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">X</span>&nbsp;=&nbsp;1<span style='letter-spacing:-.4em;'>}</span>}<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">WHILE</span>&nbsp;~(<span class="id" type="var">X</span>&nbsp;=&nbsp;0)&nbsp;<span class="id" type="var">DO</span>&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;<span class="id" type="var">X</span>&nbsp;+&nbsp;1&nbsp;<span class="id" type="var">END</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">X</span>&nbsp;=&nbsp;100<span style='letter-spacing:-.4em;'>}</span>}
<div class="paragraph"> </div>

</div>

</div>
<div class="code code-tight">
<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span><br/>
</div>

<span class="proofbox">&#9744;</span> 
<div class="doc less-space">
<div class="paragraph"> </div>

 为了热身，这里有两个关于霍尔三元组的简单定理。
    （确保你弄懂它们的意思。）
</div>
<div class="code code-tight">

<span class="id" type="keyword">Theorem</span> <span class="id" type="var">hoare_post_true</span> : <span style='font-size:120%;'>&forall;</span>(<span class="id" type="var">P</span> <span class="id" type="var">Q</span> : <span class="id" type="var">Assertion</span>) <span class="id" type="var">c</span>,<br/>
&nbsp;&nbsp;(<span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span>, <span class="id" type="var">Q</span> <span class="id" type="var">st</span>) →<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">c</span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Q</span><span style='letter-spacing:-.4em;'>}</span>}.<br/>
<div class="togglescript" id="proofcontrol1" onclick="toggleDisplay('proof1');toggleDisplay('proofcontrol1')"><span class="show"></span></div>
<div class="proofscript" id="proof1" onclick="toggleDisplay('proof1');toggleDisplay('proofcontrol1')">
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">P</span> <span class="id" type="var">Q</span> <span class="id" type="var">c</span> <span class="id" type="var">H</span>. <span class="id" type="tactic">unfold</span> <span class="id" type="var">hoare_triple</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">Heval</span> <span class="id" type="var">HP</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">H</span>. <span class="id" type="keyword">Qed</span>.<br/>
</div>

<br/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">hoare_pre_false</span> : <span style='font-size:120%;'>&forall;</span>(<span class="id" type="var">P</span> <span class="id" type="var">Q</span> : <span class="id" type="var">Assertion</span>) <span class="id" type="var">c</span>,<br/>
&nbsp;&nbsp;(<span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span>, ¬(<span class="id" type="var">P</span> <span class="id" type="var">st</span>)) →<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">c</span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Q</span><span style='letter-spacing:-.4em;'>}</span>}.<br/>
<div class="togglescript" id="proofcontrol2" onclick="toggleDisplay('proof2');toggleDisplay('proofcontrol2')"><span class="show"></span></div>
<div class="proofscript" id="proof2" onclick="toggleDisplay('proof2');toggleDisplay('proofcontrol2')">
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">P</span> <span class="id" type="var">Q</span> <span class="id" type="var">c</span> <span class="id" type="var">H</span>. <span class="id" type="tactic">unfold</span> <span class="id" type="var">hoare_triple</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">Heval</span> <span class="id" type="var">HP</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">unfold</span> <span class="id" type="var">not</span> <span class="id" type="keyword">in</span> <span class="id" type="var">H</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">H</span> <span class="id" type="keyword">in</span> <span class="id" type="var">HP</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">HP</span>. <span class="id" type="keyword">Qed</span>.<br/>
</div>
</div>

<div class="doc">
<a name="lab54"></a><h1 class="section">证明规则</h1>

<div class="paragraph"> </div>

 霍尔逻辑的目标是提供一种_组合的_ 方法，
    用来证明特定三元组的正确性。
    也即，我们希望一段程序的正确性证明的结构反映程序本身。
    为了达成这个目的，在下面的小节中，我们为不同语法形式的 Imp
    命令引入不同的推理规则：关于赋值的、关于顺序执行的、
    关于条件执行的等等。还有一些“结构的”规则用来组合它们。
    然后我们将能证明一段程序是正确的，使用这些证明规则，甚至不用展开
    <span class="inlinecode"><span class="id" type="var">hoare_triple</span></span> 的定义。 
</div>

<div class="doc">
<a name="lab55"></a><h2 class="section">赋值</h2>

<div class="paragraph"> </div>

 赋值是霍尔逻辑的规则中最基础的一个。下述是它的工作方式。

<div class="paragraph"> </div>

    考虑这个有效的霍尔三元组：

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;<span class="id" type="var">Y</span>&nbsp;=&nbsp;1&nbsp;<span style='letter-spacing:-.4em;'>}</span>}&nbsp;&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;<span class="id" type="var">Y</span>&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;<span class="id" type="var">X</span>&nbsp;=&nbsp;1&nbsp;<span style='letter-spacing:-.4em;'>}</span>}
<div class="paragraph"> </div>

</div>
    用中文讲：如果我们从一个 <span class="inlinecode"><span class="id" type="var">Y</span></span> 是 <span class="inlinecode">1</span> 的状态开始，
    然后我们把 <span class="inlinecode"><span class="id" type="var">Y</span></span> 赋给 <span class="inlinecode"><span class="id" type="var">X</span></span>，我们最终会得到一个 <span class="inlinecode"><span class="id" type="var">X</span></span> 是 <span class="inlinecode">1</span> 的状态。
    也即，“等于 <span class="inlinecode">1</span>”这个属性被从 <span class="inlinecode"><span class="id" type="var">Y</span></span> 传递给了 <span class="inlinecode"><span class="id" type="var">X</span></span>。 
<div class="paragraph"> </div>

 相似地，在

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;<span class="id" type="var">Y</span>&nbsp;+&nbsp;<span class="id" type="var">Z</span>&nbsp;=&nbsp;1&nbsp;<span style='letter-spacing:-.4em;'>}</span>}&nbsp;&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;<span class="id" type="var">Y</span>&nbsp;+&nbsp;<span class="id" type="var">Z</span>&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;<span class="id" type="var">X</span>&nbsp;=&nbsp;1&nbsp;<span style='letter-spacing:-.4em;'>}</span>}
<div class="paragraph"> </div>

</div>
    里，同样的属性（等于 <span class="inlinecode">1</span>）被从赋值命令的右侧 <span class="inlinecode"><span class="id" type="var">Y</span></span> <span class="inlinecode">+</span> <span class="inlinecode"><span class="id" type="var">Z</span></span> 传递给了 <span class="inlinecode"><span class="id" type="var">X</span></span>。
<div class="paragraph"> </div>

 更一般地, 如果 <span class="inlinecode"><span class="id" type="var">a</span></span> 是<b>任意</b>算术表达式，那么

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;<span class="id" type="var">a</span>&nbsp;=&nbsp;1&nbsp;<span style='letter-spacing:-.4em;'>}</span>}&nbsp;&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;<span class="id" type="var">a</span>&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;<span class="id" type="var">X</span>&nbsp;=&nbsp;1&nbsp;<span style='letter-spacing:-.4em;'>}</span>}
<div class="paragraph"> </div>

</div>
    是一个有效的霍尔三元组。 
<div class="paragraph"> </div>

 甚至更一般地，为了得到 <span class="inlinecode"><span class="id" type="var">Q</span></span> 在 <span class="inlinecode"><span class="id" type="var">X</span></span> <span class="inlinecode"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span></span> <span class="inlinecode"><span class="id" type="var">a</span></span> 后仍然成立，我们需要先有
    <span class="inlinecode"><span class="id" type="var">Q</span></span> 在 <span class="inlinecode"><span class="id" type="var">X</span></span> <span class="inlinecode"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span></span> <span class="inlinecode"><span class="id" type="var">a</span></span> 前成立，不过<b>所有在 <span class="inlinecode"><span class="id" type="var">Q</span></span> 中出现的</b> <span class="inlinecode"><span class="id" type="var">X</span></span> 被
    替换为 <span class="inlinecode"><span class="id" type="var">a</span></span>。这给出了霍尔逻辑中赋值的规则

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;<span class="id" type="var">Q</span>&nbsp;[<span class="id" type="var">X</span>&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span>&nbsp;<span class="id" type="var">a</span>]&nbsp;<span style='letter-spacing:-.4em;'>}</span>}&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;<span class="id" type="var">a</span>&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;<span class="id" type="var">Q</span>&nbsp;<span style='letter-spacing:-.4em;'>}</span>}
<div class="paragraph"> </div>

</div>
    其中 "<span class="inlinecode"><span class="id" type="var">Q</span></span> <span class="inlinecode">[<span class="id" type="var">X</span></span> <span class="inlinecode"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span></span> <span class="inlinecode"><span class="id" type="var">a</span>]</span>" 读作 “在 <span class="inlinecode"><span class="id" type="var">Q</span></span> 中把 <span class="inlinecode"><span class="id" type="var">X</span></span> 换成 <span class="inlinecode"><span class="id" type="var">a</span></span>”。 
<div class="paragraph"> </div>

 例如，下列这些是赋值规则正确的应用：

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;(<span class="id" type="var">X</span>&nbsp;≤&nbsp;5)&nbsp;[<span class="id" type="var">X</span>&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span>&nbsp;<span class="id" type="var">X</span>&nbsp;+&nbsp;1]<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">i.e</span>.,&nbsp;<span class="id" type="var">X</span>&nbsp;+&nbsp;1&nbsp;≤&nbsp;5&nbsp;<span style='letter-spacing:-.4em;'>}</span>}<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;<span class="id" type="var">X</span>&nbsp;+&nbsp;1<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;<span class="id" type="var">X</span>&nbsp;≤&nbsp;5&nbsp;<span style='letter-spacing:-.4em;'>}</span>}<br/>
<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;(<span class="id" type="var">X</span>&nbsp;=&nbsp;3)&nbsp;[<span class="id" type="var">X</span>&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span>&nbsp;3]<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">i.e</span>.,&nbsp;3&nbsp;=&nbsp;3&nbsp;<span style='letter-spacing:-.4em;'>}</span>}<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;3<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;<span class="id" type="var">X</span>&nbsp;=&nbsp;3&nbsp;<span style='letter-spacing:-.4em;'>}</span>}<br/>
<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;(0&nbsp;≤&nbsp;<span class="id" type="var">X</span>&nbsp;∧&nbsp;<span class="id" type="var">X</span>&nbsp;≤&nbsp;5)&nbsp;[<span class="id" type="var">X</span>&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span>&nbsp;3]<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">i.e</span>.,&nbsp;(0&nbsp;≤&nbsp;3&nbsp;∧&nbsp;3&nbsp;≤&nbsp;5)&nbsp;<span style='letter-spacing:-.4em;'>}</span>}<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;3<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;0&nbsp;≤&nbsp;<span class="id" type="var">X</span>&nbsp;∧&nbsp;<span class="id" type="var">X</span>&nbsp;≤&nbsp;5&nbsp;<span style='letter-spacing:-.4em;'>}</span>}
<div class="paragraph"> </div>

</div>

<div class="paragraph"> </div>

 为了形式化这个规则，我们必须先把“在一个断言中将 Imp 变量替换为一个
    表达式” 的概念形式化，我们把这叫做“断言替换”，或者是 <span class="inlinecode"><span class="id" type="var">assn_sub</span></span>。
    也就是说，给出命题 <span class="inlinecode"><span class="id" type="var">P</span></span>、变量 <span class="inlinecode"><span class="id" type="var">X</span></span>、算术表达式 <span class="inlinecode"><span class="id" type="var">a</span></span>，我们想要生成一个
    新的命题 <span class="inlinecode"><span class="id" type="var">P'</span></span>，它和 <span class="inlinecode"><span class="id" type="var">P</span></span> 一样，不过 <span class="inlinecode"><span class="id" type="var">P'</span></span> 应该用 <span class="inlinecode"><span class="id" type="var">a</span></span> 来取代所有
    <span class="inlinecode"><span class="id" type="var">P</span></span> 提及 <span class="inlinecode"><span class="id" type="var">X</span></span> 之处。
<div class="paragraph"> </div>

 因为 <span class="inlinecode"><span class="id" type="var">P</span></span> 是一个任意的 Coq 断言，我们不能直接“编辑”它的文本部分。不
    过，我们可以通过将 <span class="inlinecode"><span class="id" type="var">P</span></span> 在下述新的状态中计算来达到相同的效果：
</div>
<div class="code code-tight">

<span class="id" type="keyword">Definition</span> <span class="id" type="var">assn_sub</span> <span class="id" type="var">X</span> <span class="id" type="var">a</span> <span class="id" type="var">P</span> : <span class="id" type="var">Assertion</span> :=<br/>
&nbsp;&nbsp;<span class="id" type="keyword">fun</span> (<span class="id" type="var">st</span> : <span class="id" type="var">state</span>) ⇒<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">P</span> (<span class="id" type="var">X</span> !<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> <span class="id" type="var">aeval</span> <span class="id" type="var">st</span> <span class="id" type="var">a</span> ; <span class="id" type="var">st</span>).<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Notation</span> "P [ X <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span> a ]" := (<span class="id" type="var">assn_sub</span> <span class="id" type="var">X</span> <span class="id" type="var">a</span> <span class="id" type="var">P</span>)<br/>
&nbsp;&nbsp;(<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 10, <span class="id" type="var">X</span> <span class="id" type="tactic">at</span> <span class="id" type="var">next</span> <span class="id" type="var">level</span>).<br/>
</div>

<div class="doc">
也就是说，<span class="inlinecode"><span class="id" type="var">P</span></span> <span class="inlinecode">[<span class="id" type="var">X</span></span> <span class="inlinecode"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span></span> <span class="inlinecode"><span class="id" type="var">a</span>]</span> 是一个新的断言——我们把它叫做 <span class="inlinecode"><span class="id" type="var">P'</span></span> ——
    它就是 <span class="inlinecode"><span class="id" type="var">P</span></span>，不过当 <span class="inlinecode"><span class="id" type="var">P</span></span> 在当前状态中查找变量 <span class="inlinecode"><span class="id" type="var">X</span></span> 的时候，<span class="inlinecode"><span class="id" type="var">P'</span></span> 使用表
    达式 <span class="inlinecode"><span class="id" type="var">a</span></span> 的值。
<div class="paragraph"> </div>

 为了演示工作原理，我们来计算一下这几个例子中发生了些什么。首先，假设
    <span class="inlinecode"><span class="id" type="var">P'</span></span> 是 <span class="inlinecode">(<span class="id" type="var">X</span></span> <span class="inlinecode">≤</span> <span class="inlinecode">5)</span> <span class="inlinecode">[<span class="id" type="var">X</span></span> <span class="inlinecode"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span></span> <span class="inlinecode">3]</span> ——或者，更形式化地， <span class="inlinecode"><span class="id" type="var">P'</span></span> 是 Coq 表达式

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">fun</span>&nbsp;<span class="id" type="var">st</span>&nbsp;⇒<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="keyword">fun</span>&nbsp;<span class="id" type="var">st'</span>&nbsp;⇒&nbsp;<span class="id" type="var">st'</span>&nbsp;<span class="id" type="var">X</span>&nbsp;≤&nbsp;5)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">X</span>&nbsp;!<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;<span class="id" type="var">aeval</span>&nbsp;<span class="id" type="var">st</span>&nbsp;3&nbsp;;&nbsp;<span class="id" type="var">st</span>),
<div class="paragraph"> </div>

</div>
    它简化为

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">fun</span>&nbsp;<span class="id" type="var">st</span>&nbsp;⇒<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="keyword">fun</span>&nbsp;<span class="id" type="var">st'</span>&nbsp;⇒&nbsp;<span class="id" type="var">st'</span>&nbsp;<span class="id" type="var">X</span>&nbsp;≤&nbsp;5)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">X</span>&nbsp;!<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;3&nbsp;;&nbsp;<span class="id" type="var">st</span>)
<div class="paragraph"> </div>

</div>
    并且可以进一步简化为

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">fun</span>&nbsp;<span class="id" type="var">st</span>&nbsp;⇒<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((<span class="id" type="var">X</span>&nbsp;!<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;3&nbsp;;&nbsp;<span class="id" type="var">st</span>)&nbsp;<span class="id" type="var">X</span>)&nbsp;≤&nbsp;5
<div class="paragraph"> </div>

</div>
   最终是

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">fun</span>&nbsp;<span class="id" type="var">st</span>&nbsp;⇒<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;≤&nbsp;5.
<div class="paragraph"> </div>

</div>
    也就是说，<span class="inlinecode"><span class="id" type="var">P'</span></span> 是一个断言指出 <span class="inlinecode">3</span> 小于等于 <span class="inlinecode">5</span>（像我们想的一样）。
<div class="paragraph"> </div>

 一个更有趣的例子是，假设 <span class="inlinecode"><span class="id" type="var">P'</span></span> 是 <span class="inlinecode">(<span class="id" type="var">X</span></span> <span class="inlinecode">≤</span> <span class="inlinecode">5)</span> <span class="inlinecode">[<span class="id" type="var">X</span></span> <span class="inlinecode"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span></span> <span class="inlinecode"><span class="id" type="var">X</span></span> <span class="inlinecode">+</span> <span class="inlinecode">1]</span>。形式化地，<span class="inlinecode"><span class="id" type="var">P'</span></span>
    是 Coq 表达式

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">fun</span>&nbsp;<span class="id" type="var">st</span>&nbsp;⇒<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="keyword">fun</span>&nbsp;<span class="id" type="var">st'</span>&nbsp;⇒&nbsp;<span class="id" type="var">st'</span>&nbsp;<span class="id" type="var">X</span>&nbsp;≤&nbsp;5)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">X</span>&nbsp;!<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;<span class="id" type="var">aeval</span>&nbsp;<span class="id" type="var">st</span>&nbsp;(<span class="id" type="var">X</span>&nbsp;+&nbsp;1)&nbsp;;&nbsp;<span class="id" type="var">st</span>),
<div class="paragraph"> </div>

</div>
    它简化为

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">fun</span>&nbsp;<span class="id" type="var">st</span>&nbsp;⇒<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">X</span>&nbsp;!<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;<span class="id" type="var">aeval</span>&nbsp;<span class="id" type="var">st</span>&nbsp;(<span class="id" type="var">X</span>&nbsp;+&nbsp;1)&nbsp;;&nbsp;<span class="id" type="var">st</span>)&nbsp;<span class="id" type="var">X</span>&nbsp;≤&nbsp;5
<div class="paragraph"> </div>

</div>
    并且进一步简化为

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">fun</span>&nbsp;<span class="id" type="var">st</span>&nbsp;⇒<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">aeval</span>&nbsp;<span class="id" type="var">st</span>&nbsp;(<span class="id" type="var">X</span>&nbsp;+&nbsp;1))&nbsp;≤&nbsp;5.
<div class="paragraph"> </div>

</div>
    也就是说，<span class="inlinecode"><span class="id" type="var">P'</span></span> 指出 <span class="inlinecode"><span class="id" type="var">X</span></span> <span class="inlinecode">+</span> <span class="inlinecode">1</span> 最多是 <span class="inlinecode">5</span>。

<div class="paragraph"> </div>

 现在，利用替换的概念，我们可以给出下述赋值证明规则的严谨证明：
<center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">&nbsp;&nbsp;</td>
  <td class="infrulenamecol" rowspan="3">
    (hoare_asgn) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{Q&nbsp;[X&nbsp;<span class="nowrap"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span></span>&nbsp;a]<span style='letter-spacing:-.4em;'>}</span>}&nbsp;X&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;a&nbsp;<span style='letter-spacing:-.4em;'>{</span>{Q<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td></td>
</td>
</table></center>
<div class="paragraph"> </div>

 我们可以形式化地证明这个规则是正确的。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Theorem</span> <span class="id" type="var">hoare_asgn</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">Q</span> <span class="id" type="var">X</span> <span class="id" type="var">a</span>,<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Q</span> [<span class="id" type="var">X</span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span> <span class="id" type="var">a</span>]<span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">X</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">a</span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Q</span><span style='letter-spacing:-.4em;'>}</span>}.<br/>
<div class="togglescript" id="proofcontrol3" onclick="toggleDisplay('proof3');toggleDisplay('proofcontrol3')"><span class="show"></span></div>
<div class="proofscript" id="proof3" onclick="toggleDisplay('proof3');toggleDisplay('proofcontrol3')">
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">unfold</span> <span class="id" type="var">hoare_triple</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">Q</span> <span class="id" type="var">X</span> <span class="id" type="var">a</span> <span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">HE</span> <span class="id" type="var">HQ</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">HE</span>. <span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">unfold</span> <span class="id" type="var">assn_sub</span> <span class="id" type="keyword">in</span> <span class="id" type="var">HQ</span>. <span class="id" type="tactic">assumption</span>. <span class="id" type="keyword">Qed</span>.<br/>
</div>
</div>

<div class="doc">
下述是一个利用这个规则的形式化证明。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Example</span> <span class="id" type="var">assn_sub_example</span> :<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{(<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">st</span> <span class="id" type="var">X</span> &lt; 5) [<span class="id" type="var">X</span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span> <span class="id" type="var">X</span> + 1]<span style='letter-spacing:-.4em;'>}</span>}<br/>
&nbsp;&nbsp;<span class="id" type="var">X</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">X</span> + 1<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">st</span> <span class="id" type="var">X</span> &lt; 5<span style='letter-spacing:-.4em;'>}</span>}.<br/>
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;课上已完成&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">hoare_asgn</span>. <span class="id" type="keyword">Qed</span>.<br/>
</div>

<div class="doc">
当然，更加有帮助的是证明这个更简单的三元组：

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">X</span>&nbsp;&lt;&nbsp;4<span style='letter-spacing:-.4em;'>}</span>}&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;<span class="id" type="var">X</span>&nbsp;+&nbsp;1&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">X</span>&nbsp;&lt;&nbsp;5<span style='letter-spacing:-.4em;'>}</span>}
<div class="paragraph"> </div>

</div>
    我们会在下一节中了解怎么做。
<div class="paragraph"> </div>

<a name="lab56"></a><h4 class="section">练习：2 星, standard (hoare_asgn_examples)</h4>
 将下列非正式的霍尔三元组……

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;1)&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;(<span class="id" type="var">X</span>&nbsp;≤&nbsp;10)&nbsp;[<span class="id" type="var">X</span>&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span>&nbsp;2&nbsp;*&nbsp;<span class="id" type="var">X</span>]&nbsp;<span style='letter-spacing:-.4em;'>}</span>}<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;2&nbsp;*&nbsp;<span class="id" type="var">X</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;<span class="id" type="var">X</span>&nbsp;≤&nbsp;10&nbsp;<span style='letter-spacing:-.4em;'>}</span>}<br/>
<br/>
&nbsp;&nbsp;&nbsp;&nbsp;2)&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;(0&nbsp;≤&nbsp;<span class="id" type="var">X</span>&nbsp;∧&nbsp;<span class="id" type="var">X</span>&nbsp;≤&nbsp;5)&nbsp;[<span class="id" type="var">X</span>&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span>&nbsp;3]&nbsp;<span style='letter-spacing:-.4em;'>}</span>}<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;3<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;0&nbsp;≤&nbsp;<span class="id" type="var">X</span>&nbsp;∧&nbsp;<span class="id" type="var">X</span>&nbsp;≤&nbsp;5&nbsp;<span style='letter-spacing:-.4em;'>}</span>}
<div class="paragraph"> </div>

</div>
   ……翻译成正式的表达（名字叫 <span class="inlinecode"><span class="id" type="var">assn_sub_ex<sub>1</sub></span></span> 和 <span class="inlinecode"><span class="id" type="var">assn_sub_ex<sub>2</sub></span></span>）
   并且用 <span class="inlinecode"><span class="id" type="var">hoare_asgn</span></span> 来证明它们。
</div>
<div class="code code-tight">

<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span><br/><hr class='doublespaceincode'/>
<span class="comment">(*&nbsp;请勿修改下面这一行：&nbsp;*)</span><br/>
<span class="id" type="keyword">Definition</span> <span class="id" type="var">manual_grade_for_hoare_asgn_examples</span> : <span class="id" type="var">option</span> (<span class="id" type="var">nat</span>*<span class="id" type="var">string</span>) := <span class="id" type="var">None</span>.<br/>
</div>

<span class="proofbox">&#9744;</span> 
<div class="doc less-space">
<div class="paragraph"> </div>

<a name="lab57"></a><h4 class="section">练习：2 星, standard, recommended (hoare_asgn_wrong)</h4>
 几乎所有人在看赋值规则第一眼就会觉得它是反向的。如果你还感觉很
    迷惑，思考一些“正向”的规则可能有帮助。这里是一个看起来挺自然的
    霍尔三元组：
<center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">&nbsp;&nbsp;</td>
  <td class="infrulenamecol" rowspan="3">
    (hoare_asgn_wrong) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{&nbsp;True&nbsp;<span style='letter-spacing:-.4em;'>}</span>}&nbsp;X&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;a&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;X&nbsp;=&nbsp;a&nbsp;<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td></td>
</td>
</table></center>    请给出一个能说明这个规则是错误的反例，并非形式化地说明它确实
    是个反例。（提示： 这个规则量化的是所有的算术表达式 <span class="inlinecode"><span class="id" type="var">a</span></span>，你的
    反例应该包含一个使这个规则不能正确工作的 <span class="inlinecode"><span class="id" type="var">a</span></span>。）
</div>
<div class="code code-tight">

<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span><br/><hr class='doublespaceincode'/>
<span class="comment">(*&nbsp;请勿修改下面这一行：&nbsp;*)</span><br/>
<span class="id" type="keyword">Definition</span> <span class="id" type="var">manual_grade_for_hoare_asgn_wrong</span> : <span class="id" type="var">option</span> (<span class="id" type="var">nat</span>*<span class="id" type="var">string</span>) := <span class="id" type="var">None</span>.<br/>
</div>

<span class="proofbox">&#9744;</span> 
<div class="doc less-space">
<div class="paragraph"> </div>

<a name="lab58"></a><h4 class="section">练习：3 星, advanced (hoare_asgn_fwd)</h4>
 然而，通过引入一个<b>参数</b> <span class="inlinecode"><span class="id" type="var">m</span></span>（一个 Coq 整数）来记录 <span class="inlinecode"><span class="id" type="var">X</span></span> 原
    来的值，我们可以定义一个赋值的证明规则，它可以，直觉上讲，“正向地
    工作”。
<center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">&nbsp;&nbsp;</td>
  <td class="infrulenamecol" rowspan="3">
    (hoare_asgn_fwd) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{fun&nbsp;st&nbsp;⇒&nbsp;P&nbsp;st&nbsp;∧&nbsp;st&nbsp;X&nbsp;=&nbsp;m<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td></td>
</td>
<tr class="infruleassumption">
  <td class="infrule">X&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;a</td>
  <td></td>
</td>
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{fun&nbsp;st&nbsp;⇒&nbsp;P&nbsp;st'&nbsp;∧&nbsp;st&nbsp;X&nbsp;=&nbsp;aeval&nbsp;st'&nbsp;a&nbsp;<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td></td>
</td>
<tr class="infruleassumption">
  <td class="infrule">(其中&nbsp;st'&nbsp;=&nbsp;(X&nbsp;!<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;m&nbsp;;&nbsp;st))</td>
  <td></td>
</td>
</table></center>    可以注意到，在赋值发生之前我们用 <span class="inlinecode"><span class="id" type="var">X</span></span> 原来的值重新构造了状态
    <span class="inlinecode"><span class="id" type="var">st'</span></span>。证明这个规则是正确的。（注意，这个规则比 <span class="inlinecode"><span class="id" type="var">hoare_asgn</span></span> 复杂些。)

</div>
<div class="code code-tight">

<span class="id" type="keyword">Theorem</span> <span class="id" type="var">hoare_asgn_fwd</span> :<br/>
&nbsp;&nbsp;<span style='font-size:120%;'>&forall;</span><span class="id" type="var">m</span> <span class="id" type="var">a</span> <span class="id" type="var">P</span>,<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">P</span> <span class="id" type="var">st</span> ∧ <span class="id" type="var">st</span> <span class="id" type="var">X</span> = <span class="id" type="var">m</span><span style='letter-spacing:-.4em;'>}</span>}<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">X</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">a</span><br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">P</span> (<span class="id" type="var">X</span> !<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> <span class="id" type="var">m</span> ; <span class="id" type="var">st</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;∧ <span class="id" type="var">st</span> <span class="id" type="var">X</span> = <span class="id" type="var">aeval</span> (<span class="id" type="var">X</span> !<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> <span class="id" type="var">m</span> ; <span class="id" type="var">st</span>) <span class="id" type="var">a</span> <span style='letter-spacing:-.4em;'>}</span>}.<br/>
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/>
</div>

<span class="proofbox">&#9744;</span> 
<div class="doc less-space">
<div class="paragraph"> </div>

<a name="lab59"></a><h4 class="section">练习：2 星, advanced, optional (hoare_asgn_fwd_exists)</h4>
 另外一种定义正向赋值规则的方式是，对变量在赋值之前的值做存在量化。
    证明这是正确的。
<center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">&nbsp;&nbsp;</td>
  <td class="infrulenamecol" rowspan="3">
    (hoare_asgn_fwd_exists) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{fun&nbsp;st&nbsp;⇒&nbsp;P&nbsp;st<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td></td>
</td>
<tr class="infruleassumption">
  <td class="infrule">X&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;a</td>
  <td></td>
</td>
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{fun&nbsp;st&nbsp;⇒&nbsp;<span style='font-size:120%;'>&exist;</span>m,&nbsp;P&nbsp;(X&nbsp;!<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;m&nbsp;;&nbsp;st)&nbsp;∧</td>
  <td></td>
</td>
<tr class="infruleassumption">
  <td class="infrule">st&nbsp;X&nbsp;=&nbsp;aeval&nbsp;(X&nbsp;!<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;m&nbsp;;&nbsp;st)&nbsp;a&nbsp;<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td></td>
</td>
</table></center>
</div>
<div class="code code-tight">

<span class="id" type="keyword">Theorem</span> <span class="id" type="var">hoare_asgn_fwd_exists</span> :<br/>
&nbsp;&nbsp;<span style='font-size:120%;'>&forall;</span><span class="id" type="var">a</span> <span class="id" type="var">P</span>,<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">P</span> <span class="id" type="var">st</span><span style='letter-spacing:-.4em;'>}</span>}<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">X</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">a</span><br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span style='font-size:120%;'>&exist;</span><span class="id" type="var">m</span>, <span class="id" type="var">P</span> (<span class="id" type="var">X</span> !<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> <span class="id" type="var">m</span> ; <span class="id" type="var">st</span>) ∧<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> <span class="id" type="var">X</span> = <span class="id" type="var">aeval</span> (<span class="id" type="var">X</span> !<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> <span class="id" type="var">m</span> ; <span class="id" type="var">st</span>) <span class="id" type="var">a</span> <span style='letter-spacing:-.4em;'>}</span>}.<br/>
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">a</span> <span class="id" type="var">P</span>.<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/>
</div>

<span class="proofbox">&#9744;</span> 

<div class="doc">
<a name="lab60"></a><h2 class="section">缩放</h2>

<div class="paragraph"> </div>

 有的时候我们从其它证明规则中得到的前置条件和后置条件可能并不
    是我们想使用的那个情形：它们可能在逻辑上符合需要，但是有着不同的
    形式而无法和期望的情形匹配；或者我们所得到的这个三元组的前条件
    太弱，抑或是后条件太强。

<div class="paragraph"> </div>

    例如，

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{(<span class="id" type="var">X</span>&nbsp;=&nbsp;3)&nbsp;[<span class="id" type="var">X</span>&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span>&nbsp;3]<span style='letter-spacing:-.4em;'>}</span>}&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;3&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">X</span>&nbsp;=&nbsp;3<span style='letter-spacing:-.4em;'>}</span>}
<div class="paragraph"> </div>

</div>
    可以直接由赋值规则所得，而

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">True</span><span style='letter-spacing:-.4em;'>}</span>}&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;3&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">X</span>&nbsp;=&nbsp;3<span style='letter-spacing:-.4em;'>}</span>}
<div class="paragraph"> </div>

</div>
    却不行。这个三元组是有效的，不过它并不是 <span class="inlinecode"><span class="id" type="var">hoare_asgn</span></span> 的实例，因
    为 <span class="inlinecode"><span class="id" type="var">True</span></span> and <span class="inlinecode">(<span class="id" type="var">X</span></span> <span class="inlinecode">=</span> <span class="inlinecode">3)</span> <span class="inlinecode">[<span class="id" type="var">X</span></span> <span class="inlinecode"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span></span> <span class="inlinecode">3]</span> 在语法上并不是相同的断言。然而，
    它们在逻辑上<b>等价</b>，所以前面那个三元组成立，后者也一定成立。
    我们把这种想法用下列规则写出来：
<center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{P'<span style='letter-spacing:-.4em;'>}</span>}&nbsp;c&nbsp;<span style='letter-spacing:-.4em;'>{</span>{Q<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td></td>
</td>
<tr class="infruleassumption">
  <td class="infrule">P&nbsp;<span class="nowrap"><span class="nowrap"><span style='font-size:85%;'><span style='letter-spacing:-.2em;'><<</span><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>></span>></span></span></span>&nbsp;P'</td>
  <td class="infrulenamecol" rowspan="3">
    (hoare_consequence_pre_equiv) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{P<span style='letter-spacing:-.4em;'>}</span>}&nbsp;c&nbsp;<span style='letter-spacing:-.4em;'>{</span>{Q<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td></td>
</td>
</table></center>
<div class="paragraph"> </div>

 仔细考虑一下这个想法，我们可以看到对一个有效的三元组加强前置条件
    或者减弱后置条件总是能得到一个有效的三元组。这种想法可以用两条
    <b>缩放规则（Rules of Consequence）</b> 来描述：
<center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{P'<span style='letter-spacing:-.4em;'>}</span>}&nbsp;c&nbsp;<span style='letter-spacing:-.4em;'>{</span>{Q<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td></td>
</td>
<tr class="infruleassumption">
  <td class="infrule">P&nbsp;<span class="nowrap"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>></span>></span></span></span>&nbsp;P'</td>
  <td class="infrulenamecol" rowspan="3">
    (hoare_consequence_pre) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{P<span style='letter-spacing:-.4em;'>}</span>}&nbsp;c&nbsp;<span style='letter-spacing:-.4em;'>{</span>{Q<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td></td>
</td>
</table></center><center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{P<span style='letter-spacing:-.4em;'>}</span>}&nbsp;c&nbsp;<span style='letter-spacing:-.4em;'>{</span>{Q'<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td></td>
</td>
<tr class="infruleassumption">
  <td class="infrule">Q'&nbsp;<span class="nowrap"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>></span>></span></span></span>&nbsp;Q</td>
  <td class="infrulenamecol" rowspan="3">
    (hoare_consequence_post) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{P<span style='letter-spacing:-.4em;'>}</span>}&nbsp;c&nbsp;<span style='letter-spacing:-.4em;'>{</span>{Q<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td></td>
</td>
</table></center>
<div class="paragraph"> </div>

 下列是形式化的版本： 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Theorem</span> <span class="id" type="var">hoare_consequence_pre</span> : <span style='font-size:120%;'>&forall;</span>(<span class="id" type="var">P</span> <span class="id" type="var">P'</span> <span class="id" type="var">Q</span> : <span class="id" type="var">Assertion</span>) <span class="id" type="var">c</span>,<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P'</span><span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">c</span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Q</span><span style='letter-spacing:-.4em;'>}</span>} →<br/>
&nbsp;&nbsp;<span class="id" type="var">P</span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>></span>></span></span> <span class="id" type="var">P'</span> →<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">c</span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Q</span><span style='letter-spacing:-.4em;'>}</span>}.<br/>
<div class="togglescript" id="proofcontrol4" onclick="toggleDisplay('proof4');toggleDisplay('proofcontrol4')"><span class="show"></span></div>
<div class="proofscript" id="proof4" onclick="toggleDisplay('proof4');toggleDisplay('proofcontrol4')">
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">P</span> <span class="id" type="var">P'</span> <span class="id" type="var">Q</span> <span class="id" type="var">c</span> <span class="id" type="var">Hhoare</span> <span class="id" type="var">Himp</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">Hc</span> <span class="id" type="var">HP</span>. <span class="id" type="tactic">apply</span> (<span class="id" type="var">Hhoare</span> <span class="id" type="var">st</span> <span class="id" type="var">st'</span>).<br/>
&nbsp;&nbsp;<span class="id" type="tactic">assumption</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">Himp</span>. <span class="id" type="tactic">assumption</span>. <span class="id" type="keyword">Qed</span>.<br/>
</div>

<br/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">hoare_consequence_post</span> : <span style='font-size:120%;'>&forall;</span>(<span class="id" type="var">P</span> <span class="id" type="var">Q</span> <span class="id" type="var">Q'</span> : <span class="id" type="var">Assertion</span>) <span class="id" type="var">c</span>,<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">c</span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Q'</span><span style='letter-spacing:-.4em;'>}</span>} →<br/>
&nbsp;&nbsp;<span class="id" type="var">Q'</span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>></span>></span></span> <span class="id" type="var">Q</span> →<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">c</span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Q</span><span style='letter-spacing:-.4em;'>}</span>}.<br/>
<div class="togglescript" id="proofcontrol5" onclick="toggleDisplay('proof5');toggleDisplay('proofcontrol5')"><span class="show"></span></div>
<div class="proofscript" id="proof5" onclick="toggleDisplay('proof5');toggleDisplay('proofcontrol5')">
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">P</span> <span class="id" type="var">Q</span> <span class="id" type="var">Q'</span> <span class="id" type="var">c</span> <span class="id" type="var">Hhoare</span> <span class="id" type="var">Himp</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">Hc</span> <span class="id" type="var">HP</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">Himp</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">apply</span> (<span class="id" type="var">Hhoare</span> <span class="id" type="var">st</span> <span class="id" type="var">st'</span>).<br/>
&nbsp;&nbsp;<span class="id" type="tactic">assumption</span>. <span class="id" type="tactic">assumption</span>. <span class="id" type="keyword">Qed</span>.<br/>
</div>
</div>

<div class="doc">
例如，我们可以这样应用第一条规则：

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;<span class="id" type="var">True</span>&nbsp;<span style='letter-spacing:-.4em;'>}</span>}&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>></span>></span></span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;1&nbsp;=&nbsp;1&nbsp;<span style='letter-spacing:-.4em;'>}</span>}<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;1<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;<span class="id" type="var">X</span>&nbsp;=&nbsp;1&nbsp;<span style='letter-spacing:-.4em;'>}</span>}
<div class="paragraph"> </div>

</div>
    或者，形式化地：
</div>
<div class="code code-tight">

<span class="id" type="keyword">Example</span> <span class="id" type="var">hoare_asgn_example1</span> :<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">True</span><span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">X</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> 1 <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">st</span> <span class="id" type="var">X</span> = 1<span style='letter-spacing:-.4em;'>}</span>}.<br/>
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;课上已完成&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">hoare_consequence_pre</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">with</span> (<span class="id" type="var">P'</span> := (<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">st</span> <span class="id" type="var">X</span> = 1) [<span class="id" type="var">X</span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span> 1]).<br/>
&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">hoare_asgn</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">st</span> <span class="id" type="var">H</span>. <span class="id" type="tactic">unfold</span> <span class="id" type="var">assn_sub</span>, <span class="id" type="var">t_update</span>. <span class="id" type="tactic">simpl</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
<span class="id" type="keyword">Qed</span>.<br/>
</div>

<div class="doc">
我们也可以用它来证明之前提到的例子。

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;<span class="id" type="var">X</span>&nbsp;&lt;&nbsp;4&nbsp;<span style='letter-spacing:-.4em;'>}</span>}&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>></span>></span></span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;(<span class="id" type="var">X</span>&nbsp;&lt;&nbsp;5)[<span class="id" type="var">X</span>&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span>&nbsp;<span class="id" type="var">X</span>&nbsp;+&nbsp;1]&nbsp;<span style='letter-spacing:-.4em;'>}</span>}<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;<span class="id" type="var">X</span>&nbsp;+&nbsp;1<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;<span class="id" type="var">X</span>&nbsp;&lt;&nbsp;5&nbsp;<span style='letter-spacing:-.4em;'>}</span>}
<div class="paragraph"> </div>

</div>
   或者，形式化地：
</div>
<div class="code code-tight">

<span class="id" type="keyword">Example</span> <span class="id" type="var">assn_sub_example2</span> :<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{(<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">st</span> <span class="id" type="var">X</span> &lt; 4)<span style='letter-spacing:-.4em;'>}</span>}<br/>
&nbsp;&nbsp;<span class="id" type="var">X</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">X</span> + 1<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">st</span> <span class="id" type="var">X</span> &lt; 5<span style='letter-spacing:-.4em;'>}</span>}.<br/>
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;课上已完成&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">hoare_consequence_pre</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">with</span> (<span class="id" type="var">P'</span> := (<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">st</span> <span class="id" type="var">X</span> &lt; 5) [<span class="id" type="var">X</span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span> <span class="id" type="var">X</span> + 1]).<br/>
&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">hoare_asgn</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">st</span> <span class="id" type="var">H</span>. <span class="id" type="tactic">unfold</span> <span class="id" type="var">assn_sub</span>, <span class="id" type="var">t_update</span>. <span class="id" type="tactic">simpl</span>. <span class="id" type="tactic">omega</span>.<br/>
<span class="id" type="keyword">Qed</span>.<br/>
</div>

<div class="doc">
最后，为了证明中的方便，我们有一个组合起来的缩放规则，可以让
    我们同时改变前置条件和后置条件。
<center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{P'<span style='letter-spacing:-.4em;'>}</span>}&nbsp;c&nbsp;<span style='letter-spacing:-.4em;'>{</span>{Q'<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td></td>
</td>
<tr class="infruleassumption">
  <td class="infrule">P&nbsp;<span class="nowrap"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>></span>></span></span></span>&nbsp;P'</td>
  <td></td>
</td>
<tr class="infruleassumption">
  <td class="infrule">Q'&nbsp;<span class="nowrap"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>></span>></span></span></span>&nbsp;Q</td>
  <td class="infrulenamecol" rowspan="3">
    (hoare_consequence) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{P<span style='letter-spacing:-.4em;'>}</span>}&nbsp;c&nbsp;<span style='letter-spacing:-.4em;'>{</span>{Q<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td></td>
</td>
</table></center>
</div>
<div class="code code-tight">

<span class="id" type="keyword">Theorem</span> <span class="id" type="var">hoare_consequence</span> : <span style='font-size:120%;'>&forall;</span>(<span class="id" type="var">P</span> <span class="id" type="var">P'</span> <span class="id" type="var">Q</span> <span class="id" type="var">Q'</span> : <span class="id" type="var">Assertion</span>) <span class="id" type="var">c</span>,<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P'</span><span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">c</span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Q'</span><span style='letter-spacing:-.4em;'>}</span>} →<br/>
&nbsp;&nbsp;<span class="id" type="var">P</span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>></span>></span></span> <span class="id" type="var">P'</span> →<br/>
&nbsp;&nbsp;<span class="id" type="var">Q'</span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>></span>></span></span> <span class="id" type="var">Q</span> →<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">c</span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Q</span><span style='letter-spacing:-.4em;'>}</span>}.<br/>
<div class="togglescript" id="proofcontrol6" onclick="toggleDisplay('proof6');toggleDisplay('proofcontrol6')"><span class="show"></span></div>
<div class="proofscript" id="proof6" onclick="toggleDisplay('proof6');toggleDisplay('proofcontrol6')">
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">P</span> <span class="id" type="var">P'</span> <span class="id" type="var">Q</span> <span class="id" type="var">Q'</span> <span class="id" type="var">c</span> <span class="id" type="var">Hht</span> <span class="id" type="var">HPP'</span> <span class="id" type="var">HQ'Q</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">hoare_consequence_pre</span> <span class="id" type="keyword">with</span> (<span class="id" type="var">P'</span> := <span class="id" type="var">P'</span>).<br/>
&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">hoare_consequence_post</span> <span class="id" type="keyword">with</span> (<span class="id" type="var">Q'</span> := <span class="id" type="var">Q'</span>).<br/>
&nbsp;&nbsp;<span class="id" type="tactic">assumption</span>. <span class="id" type="tactic">assumption</span>. <span class="id" type="tactic">assumption</span>. <span class="id" type="keyword">Qed</span>.<br/>
</div>
</div>

<div class="doc">
<a name="lab61"></a><h2 class="section">题外话：<span class="inlinecode"><span class="id" type="tactic">eapply</span></span> 策略</h2>

<div class="paragraph"> </div>

 这又是一个来看一下 <span class="inlinecode"><span class="id" type="tactic">eapply</span></span> 策略的好机会。我们在逻辑基础的
    <a href="https://coq-zh.github.io/SF-zh/lf-current/Auto.html"><span class="inlineref">Auto</span></a> 一章中已经简略介绍过了。

<div class="paragraph"> </div>

    在 <span class="inlinecode"><span class="id" type="var">hoare_asgn_example1</span></span> 和 <span class="inlinecode"><span class="id" type="var">hoare_consequence</span></span> 中，我们必
    须要显式地写出 “<span class="inlinecode"><span class="id" type="keyword">with</span></span> <span class="inlinecode">(<span class="id" type="var">P'</span></span> <span class="inlinecode">:=</span> <span class="inlinecode">...)</span>” 来保证 <span class="inlinecode"><span class="id" type="var">hoare_consequence</span></span>
    中假定的所有元变量都被设为了一个具体的值。（这是因为 <span class="inlinecode"><span class="id" type="var">P'</span></span>
    没有在 <span class="inlinecode"><span class="id" type="var">hoare_consequence_pre</span></span> 的结论中出现，将结论匹配于
    当前的目标并不能把 <span class="inlinecode"><span class="id" type="var">P'</span></span> 约束到一个具体的断言上。）

<div class="paragraph"> </div>

    这很烦人，既因为这个断言有点长，而且，在 <span class="inlinecode"><span class="id" type="var">hoare_asgn_example1</span></span> 中，
    我们紧接着的下一步——应用 <span class="inlinecode"><span class="id" type="var">hoare_asgn</span></span> 规则——将会直接给出
    这个断言应该是什么！这时，我们可以用 <span class="inlinecode"><span class="id" type="tactic">eapply</span></span> 代替 <span class="inlinecode"><span class="id" type="tactic">apply</span></span>
    来告诉 Coq，大概是“耐心点儿：空缺的那部分会在证明中过会儿
    再填上。” 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Example</span> <span class="id" type="var">hoare_asgn_example1'</span> :<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">True</span><span style='letter-spacing:-.4em;'>}</span>}<br/>
&nbsp;&nbsp;<span class="id" type="var">X</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> 1<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">st</span> <span class="id" type="var">X</span> = 1<span style='letter-spacing:-.4em;'>}</span>}.<br/>
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">hoare_consequence_pre</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">hoare_asgn</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">st</span> <span class="id" type="var">H</span>. <span class="id" type="tactic">reflexivity</span>. <span class="id" type="keyword">Qed</span>.<br/>
</div>

<div class="doc">
一般来说，<span class="inlinecode"><span class="id" type="tactic">eapply</span></span> <span class="inlinecode"><span class="id" type="var">H</span></span> 策略和 <span class="inlinecode"><span class="id" type="tactic">apply</span></span> <span class="inlinecode"><span class="id" type="var">H</span></span> 的工作方式相同，不过
    当匹配目标和 <span class="inlinecode"><span class="id" type="var">H</span></span> 的结论时，若无法确定如何实例化 <span class="inlinecode"><span class="id" type="var">H</span></span> 的前提中出
    现的变量，<span class="inlinecode"><span class="id" type="tactic">eapply</span></span> <span class="inlinecode"><span class="id" type="var">H</span></span> 并不会失败，而是会把这些变量
    替换为<b>存在变量（existential variables）</b>（写做 <span class="inlinecode">?<span class="id" type="var">nnn</span></span>）,
    它的功能是作为接下来证明中会确定（通过进一步的合一）
    的变量的占位符。
<div class="paragraph"> </div>

 如果要 <span class="inlinecode"><span class="id" type="keyword">Qed</span></span> 成功，所有的存在变量都要在证明结束前被确定。
    否则 Coq 将会（正义地）拒绝接受这个证明。回想，Coq 策略
    将构建证明对象，证明对象中还有一些存在变量没有被确定。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Lemma</span> <span class="id" type="var">silly1</span> : <span style='font-size:120%;'>&forall;</span>(<span class="id" type="var">P</span> : <span class="id" type="var">nat</span> → <span class="id" type="var">nat</span> → <span class="id" type="keyword">Prop</span>) (<span class="id" type="var">Q</span> : <span class="id" type="var">nat</span> → <span class="id" type="keyword">Prop</span>),<br/>
&nbsp;&nbsp;(<span style='font-size:120%;'>&forall;</span><span class="id" type="var">x</span> <span class="id" type="var">y</span> : <span class="id" type="var">nat</span>, <span class="id" type="var">P</span> <span class="id" type="var">x</span> <span class="id" type="var">y</span>) →<br/>
&nbsp;&nbsp;(<span style='font-size:120%;'>&forall;</span><span class="id" type="var">x</span> <span class="id" type="var">y</span> : <span class="id" type="var">nat</span>, <span class="id" type="var">P</span> <span class="id" type="var">x</span> <span class="id" type="var">y</span> → <span class="id" type="var">Q</span> <span class="id" type="var">x</span>) →<br/>
&nbsp;&nbsp;<span class="id" type="var">Q</span> 42.<br/>
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">P</span> <span class="id" type="var">Q</span> <span class="id" type="var">HP</span> <span class="id" type="var">HQ</span>. <span class="id" type="tactic">eapply</span> <span class="id" type="var">HQ</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">HP</span>.<br/>
</div>

<div class="doc">
Coq 在 <span class="inlinecode"><span class="id" type="tactic">apply</span></span> <span class="inlinecode"><span class="id" type="var">HP</span></span> 之后提出了一个警告。（“All the remaining goals
    are on the shelf”，意思是我们已经完成了所有的顶层的证明目标，
    然而在这个过程中我们将一些放到一边打算待会做，我们还没有完成它们。）
    用 <span class="inlinecode"><span class="id" type="keyword">Qed</span></span> 结束证明会产生一个错误。
</div>
<div class="code code-tight">
<span class="id" type="keyword">Abort</span>.<br/>
</div>

<div class="doc">
一个附加的限制是，若项中含有在创建存在变量时还不存在的普通变量，则存在变量无法被实例化。
   （原因当然是如果我们允许这样做逻辑系统就会变得不再自洽。） 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Lemma</span> <span class="id" type="var">silly2</span> :<br/>
&nbsp;&nbsp;<span style='font-size:120%;'>&forall;</span>(<span class="id" type="var">P</span> : <span class="id" type="var">nat</span> → <span class="id" type="var">nat</span> → <span class="id" type="keyword">Prop</span>) (<span class="id" type="var">Q</span> : <span class="id" type="var">nat</span> → <span class="id" type="keyword">Prop</span>),<br/>
&nbsp;&nbsp;(<span style='font-size:120%;'>&exist;</span><span class="id" type="var">y</span>, <span class="id" type="var">P</span> 42 <span class="id" type="var">y</span>) →<br/>
&nbsp;&nbsp;(<span style='font-size:120%;'>&forall;</span><span class="id" type="var">x</span> <span class="id" type="var">y</span> : <span class="id" type="var">nat</span>, <span class="id" type="var">P</span> <span class="id" type="var">x</span> <span class="id" type="var">y</span> → <span class="id" type="var">Q</span> <span class="id" type="var">x</span>) →<br/>
&nbsp;&nbsp;<span class="id" type="var">Q</span> 42.<br/>
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">P</span> <span class="id" type="var">Q</span> <span class="id" type="var">HP</span> <span class="id" type="var">HQ</span>. <span class="id" type="tactic">eapply</span> <span class="id" type="var">HQ</span>. <span class="id" type="tactic">destruct</span> <span class="id" type="var">HP</span> <span class="id" type="keyword">as</span> [<span class="id" type="var">y</span> <span class="id" type="var">HP'</span>].<br/>
</div>

<div class="doc">
在这里使用 <span class="inlinecode"><span class="id" type="tactic">apply</span></span> <span class="inlinecode"><span class="id" type="var">HP'</span></span> 将会失败并产生如下错误：

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Error</span>:&nbsp;<span class="id" type="var">Impossible</span>&nbsp;<span class="id" type="var">to</span>&nbsp;<span class="id" type="var">unify</span>&nbsp;"?175"&nbsp;<span class="id" type="keyword">with</span>&nbsp;"y".
<div class="paragraph"> </div>

</div>
    有一个简单的解决办法：把 <span class="inlinecode"><span class="id" type="tactic">destruct</span></span> <span class="inlinecode"><span class="id" type="var">HP</span></span> 提到 <span class="inlinecode"><span class="id" type="tactic">eapply</span></span> <span class="inlinecode"><span class="id" type="var">HQ</span></span> <b>之前</b>。 
</div>
<div class="code code-tight">
<span class="id" type="keyword">Abort</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Lemma</span> <span class="id" type="var">silly2_fixed</span> :<br/>
&nbsp;&nbsp;<span style='font-size:120%;'>&forall;</span>(<span class="id" type="var">P</span> : <span class="id" type="var">nat</span> → <span class="id" type="var">nat</span> → <span class="id" type="keyword">Prop</span>) (<span class="id" type="var">Q</span> : <span class="id" type="var">nat</span> → <span class="id" type="keyword">Prop</span>),<br/>
&nbsp;&nbsp;(<span style='font-size:120%;'>&exist;</span><span class="id" type="var">y</span>, <span class="id" type="var">P</span> 42 <span class="id" type="var">y</span>) →<br/>
&nbsp;&nbsp;(<span style='font-size:120%;'>&forall;</span><span class="id" type="var">x</span> <span class="id" type="var">y</span> : <span class="id" type="var">nat</span>, <span class="id" type="var">P</span> <span class="id" type="var">x</span> <span class="id" type="var">y</span> → <span class="id" type="var">Q</span> <span class="id" type="var">x</span>) →<br/>
&nbsp;&nbsp;<span class="id" type="var">Q</span> 42.<br/>
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">P</span> <span class="id" type="var">Q</span> <span class="id" type="var">HP</span> <span class="id" type="var">HQ</span>. <span class="id" type="tactic">destruct</span> <span class="id" type="var">HP</span> <span class="id" type="keyword">as</span> [<span class="id" type="var">y</span> <span class="id" type="var">HP'</span>].<br/>
&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">HQ</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">HP'</span>.<br/>
<span class="id" type="keyword">Qed</span>.<br/>
</div>

<div class="doc">
最后一步中的 <span class="inlinecode"><span class="id" type="tactic">apply</span></span> <span class="inlinecode"><span class="id" type="var">HP'</span></span> 将目标中的存在变量匹配于变量 <span class="inlinecode"><span class="id" type="var">y</span></span>。

<div class="paragraph"> </div>

    注意，<span class="inlinecode"><span class="id" type="tactic">assumption</span></span> 策略并不能在这里正常工作，因为它不能处理
    存在变量。然而，Coq 也提供了一个 <span class="inlinecode"><span class="id" type="var">eassumption</span></span> 策略，如果当
    前有一个前提通过将结论中的存在变量填好而匹配，它就解决目标。
    我们可以用它来代替 <span class="inlinecode"><span class="id" type="tactic">apply</span></span> <span class="inlinecode"><span class="id" type="var">HP'</span></span>，如果你想的话。 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Lemma</span> <span class="id" type="var">silly2_eassumption</span> : <span style='font-size:120%;'>&forall;</span>(<span class="id" type="var">P</span> : <span class="id" type="var">nat</span> → <span class="id" type="var">nat</span> → <span class="id" type="keyword">Prop</span>) (<span class="id" type="var">Q</span> : <span class="id" type="var">nat</span> → <span class="id" type="keyword">Prop</span>),<br/>
&nbsp;&nbsp;(<span style='font-size:120%;'>&exist;</span><span class="id" type="var">y</span>, <span class="id" type="var">P</span> 42 <span class="id" type="var">y</span>) →<br/>
&nbsp;&nbsp;(<span style='font-size:120%;'>&forall;</span><span class="id" type="var">x</span> <span class="id" type="var">y</span> : <span class="id" type="var">nat</span>, <span class="id" type="var">P</span> <span class="id" type="var">x</span> <span class="id" type="var">y</span> → <span class="id" type="var">Q</span> <span class="id" type="var">x</span>) →<br/>
&nbsp;&nbsp;<span class="id" type="var">Q</span> 42.<br/>
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">P</span> <span class="id" type="var">Q</span> <span class="id" type="var">HP</span> <span class="id" type="var">HQ</span>. <span class="id" type="tactic">destruct</span> <span class="id" type="var">HP</span> <span class="id" type="keyword">as</span> [<span class="id" type="var">y</span> <span class="id" type="var">HP'</span>]. <span class="id" type="tactic">eapply</span> <span class="id" type="var">HQ</span>. <span class="id" type="var">eassumption</span>.<br/>
<span class="id" type="keyword">Qed</span>.<br/>
</div>

<div class="doc">
<a name="lab62"></a><h4 class="section">练习：2 星, standard (hoare_asgn_examples_2)</h4>
 将下述的非形式化霍尔三元组

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;<span class="id" type="var">X</span>&nbsp;+&nbsp;1&nbsp;≤&nbsp;5&nbsp;<span style='letter-spacing:-.4em;'>}</span>}&nbsp;&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;<span class="id" type="var">X</span>&nbsp;+&nbsp;1&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;<span class="id" type="var">X</span>&nbsp;≤&nbsp;5&nbsp;<span style='letter-spacing:-.4em;'>}</span>}<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;0&nbsp;≤&nbsp;3&nbsp;∧&nbsp;3&nbsp;≤&nbsp;5&nbsp;<span style='letter-spacing:-.4em;'>}</span>}&nbsp;&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;3&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;0&nbsp;≤&nbsp;<span class="id" type="var">X</span>&nbsp;∧&nbsp;<span class="id" type="var">X</span>&nbsp;≤&nbsp;5&nbsp;<span style='letter-spacing:-.4em;'>}</span>}
<div class="paragraph"> </div>

</div>
   翻译成正式的表达（把它们叫做 <span class="inlinecode"><span class="id" type="var">assn_sub_ex<sub>1</sub>'</span></span> 和 <span class="inlinecode"><span class="id" type="var">assn_sub_ex<sub>2</sub>'</span></span>）
   并且使用 <span class="inlinecode"><span class="id" type="var">hoare_asgn</span></span> 和 <span class="inlinecode"><span class="id" type="var">hoare_consequence_pre</span></span> 证明它们。 
</div>
<div class="code code-tight">

<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span><br/><hr class='doublespaceincode'/>
<span class="comment">(*&nbsp;请勿修改下面这一行：&nbsp;*)</span><br/>
<span class="id" type="keyword">Definition</span> <span class="id" type="var">manual_grade_for_hoare_asgn_examples_2</span> : <span class="id" type="var">option</span> (<span class="id" type="var">nat</span>*<span class="id" type="var">string</span>) := <span class="id" type="var">None</span>.<br/>
</div>

<span class="proofbox">&#9744;</span> 

<div class="doc">
<a name="lab63"></a><h2 class="section">跳过</h2>

<div class="paragraph"> </div>

 因为 <span class="inlinecode"><span class="id" type="var">SKIP</span></span> 并不改变当前状态，它会保持 <span class="inlinecode"><span class="id" type="var">P</span></span>：
<center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">&nbsp;&nbsp;</td>
  <td class="infrulenamecol" rowspan="3">
    (hoare_skip) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{&nbsp;P&nbsp;<span style='letter-spacing:-.4em;'>}</span>}&nbsp;SKIP&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;P&nbsp;<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td></td>
</td>
</table></center>
</div>
<div class="code code-tight">

<span class="id" type="keyword">Theorem</span> <span class="id" type="var">hoare_skip</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">P</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">SKIP</span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>}.<br/>
<div class="togglescript" id="proofcontrol7" onclick="toggleDisplay('proof7');toggleDisplay('proofcontrol7')"><span class="show"></span></div>
<div class="proofscript" id="proof7" onclick="toggleDisplay('proof7');toggleDisplay('proofcontrol7')">
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">P</span> <span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">H</span> <span class="id" type="var">HP</span>. <span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span>. <span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">assumption</span>. <span class="id" type="keyword">Qed</span>.<br/>
</div>
</div>

<div class="doc">
<a name="lab64"></a><h2 class="section">顺序</h2>

<div class="paragraph"> </div>

 更加有趣的是，如果命令 <span class="inlinecode"><span class="id" type="var">c<sub>1</sub></span></span> 将一个 <span class="inlinecode"><span class="id" type="var">P</span></span> 成立的状态转变为 <span class="inlinecode"><span class="id" type="var">Q</span></span>
    成立的状态，而如果 <span class="inlinecode"><span class="id" type="var">c<sub>2</sub></span></span> 将 <span class="inlinecode"><span class="id" type="var">Q</span></span> 成立的状态转变为 <span class="inlinecode"><span class="id" type="var">R</span></span> 成立的，
    那么先执行 <span class="inlinecode"><span class="id" type="var">c<sub>1</sub></span></span> 然后执行 <span class="inlinecode"><span class="id" type="var">c<sub>2</sub></span></span> 将会把一个 <span class="inlinecode"><span class="id" type="var">P</span></span> 成立的状态转变
    为一个 <span class="inlinecode"><span class="id" type="var">R</span></span> 成立的状态：
<center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{&nbsp;P&nbsp;<span style='letter-spacing:-.4em;'>}</span>}&nbsp;c<sub>1</sub>&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;Q&nbsp;<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td></td>
</td>
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{&nbsp;Q&nbsp;<span style='letter-spacing:-.4em;'>}</span>}&nbsp;c<sub>2</sub>&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;R&nbsp;<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td class="infrulenamecol" rowspan="3">
    (hoare_seq) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{&nbsp;P&nbsp;<span style='letter-spacing:-.4em;'>}</span>}&nbsp;c<sub>1</sub>;;c<sub>2</sub>&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;R&nbsp;<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td></td>
</td>
</table></center>
</div>
<div class="code code-tight">

<span class="id" type="keyword">Theorem</span> <span class="id" type="var">hoare_seq</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">P</span> <span class="id" type="var">Q</span> <span class="id" type="var">R</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Q</span><span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">c<sub>2</sub></span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">R</span><span style='letter-spacing:-.4em;'>}</span>} →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">c<sub>1</sub></span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Q</span><span style='letter-spacing:-.4em;'>}</span>} →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">c<sub>1</sub></span>;;<span class="id" type="var">c<sub>2</sub></span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">R</span><span style='letter-spacing:-.4em;'>}</span>}.<br/>
<div class="togglescript" id="proofcontrol8" onclick="toggleDisplay('proof8');toggleDisplay('proofcontrol8')"><span class="show"></span></div>
<div class="proofscript" id="proof8" onclick="toggleDisplay('proof8');toggleDisplay('proofcontrol8')">
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">P</span> <span class="id" type="var">Q</span> <span class="id" type="var">R</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">H<sub>1</sub></span> <span class="id" type="var">H<sub>2</sub></span> <span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">H<sub>12</sub></span> <span class="id" type="var">Pre</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">H<sub>12</sub></span>; <span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">apply</span> (<span class="id" type="var">H<sub>1</sub></span> <span class="id" type="var">st'0</span> <span class="id" type="var">st'</span>); <span class="id" type="tactic">try</span> <span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">apply</span> (<span class="id" type="var">H<sub>2</sub></span> <span class="id" type="var">st</span> <span class="id" type="var">st'0</span>); <span class="id" type="tactic">assumption</span>. <span class="id" type="keyword">Qed</span>.<br/>
</div>
</div>

<div class="doc">
可以注意到在 <span class="inlinecode"><span class="id" type="var">hoare_seq</span></span> 中，前提以一个相反的顺序给出
    （先 <span class="inlinecode"><span class="id" type="var">c<sub>2</sub></span></span> 再 <span class="inlinecode"><span class="id" type="var">c<sub>1</sub></span></span>）。这符合在大部分情况中自然的信息输入顺序，
    因为最自然的构造一个霍尔逻辑证明的方式是从这个程序的末尾开始
    （在后置条件的状态中），然后逆推直到程序开始的地方。 
<div class="paragraph"> </div>

 一种非形式化地展示利用组合规则的证明的方式是将其写为“带标注
    的程序”，其中中间状态断言 <span class="inlinecode"><span class="id" type="var">Q</span></span> 写在 <span class="inlinecode"><span class="id" type="var">c<sub>1</sub></span></span> 和 <span class="inlinecode"><span class="id" type="var">c<sub>2</sub></span></span> 之间：

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;<span class="id" type="var">a</span>&nbsp;=&nbsp;<span class="id" type="var">n</span>&nbsp;<span style='letter-spacing:-.4em;'>}</span>}<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;<span class="id" type="var">a</span>;;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;<span class="id" type="var">X</span>&nbsp;=&nbsp;<span class="id" type="var">n</span>&nbsp;<span style='letter-spacing:-.4em;'>}</span>}&nbsp;&nbsp;&nbsp;&nbsp;&lt;---&nbsp;<span class="id" type="var">decoration</span>&nbsp;<span class="id" type="keyword">for</span>&nbsp;<span class="id" type="var">Q</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">SKIP</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;<span class="id" type="var">X</span>&nbsp;=&nbsp;<span class="id" type="var">n</span>&nbsp;<span style='letter-spacing:-.4em;'>}</span>}
<div class="paragraph"> </div>

</div>

<div class="paragraph"> </div>

 下面是一个同时包括赋值和组合的例子。 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Example</span> <span class="id" type="var">hoare_asgn_example3</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">a</span> <span class="id" type="var">n</span>,<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">aeval</span> <span class="id" type="var">st</span> <span class="id" type="var">a</span> = <span class="id" type="var">n</span><span style='letter-spacing:-.4em;'>}</span>}<br/>
&nbsp;&nbsp;<span class="id" type="var">X</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">a</span>;; <span class="id" type="var">SKIP</span><br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">st</span> <span class="id" type="var">X</span> = <span class="id" type="var">n</span><span style='letter-spacing:-.4em;'>}</span>}.<br/>
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">a</span> <span class="id" type="var">n</span>. <span class="id" type="tactic">eapply</span> <span class="id" type="var">hoare_seq</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;组合右侧&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">hoare_skip</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;组合左侧&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">hoare_consequence_pre</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">hoare_asgn</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">st</span> <span class="id" type="var">H</span>. <span class="id" type="tactic">subst</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
<span class="id" type="keyword">Qed</span>.<br/>
</div>

<div class="doc">
我们一般会将 <span class="inlinecode"><span class="id" type="var">hoare_seq</span></span> 和
    <span class="inlinecode"><span class="id" type="var">hoare_consequence_pre</span></span> 以及 <span class="inlinecode"><span class="id" type="tactic">eapply</span></span> 策略一起使用，如上所示。
<div class="paragraph"> </div>

<a name="lab65"></a><h4 class="section">练习：2 星, standard, recommended (hoare_asgn_example4)</h4>
 将这个“标注程序”翻译成正式证明：

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;<span class="id" type="var">True</span>&nbsp;<span style='letter-spacing:-.4em;'>}</span>}&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>></span>></span></span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;1&nbsp;=&nbsp;1&nbsp;<span style='letter-spacing:-.4em;'>}</span>}<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;1;;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;<span class="id" type="var">X</span>&nbsp;=&nbsp;1&nbsp;<span style='letter-spacing:-.4em;'>}</span>}&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>></span>></span></span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;<span class="id" type="var">X</span>&nbsp;=&nbsp;1&nbsp;∧&nbsp;2&nbsp;=&nbsp;2&nbsp;<span style='letter-spacing:-.4em;'>}</span>}<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Y</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;2<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;<span class="id" type="var">X</span>&nbsp;=&nbsp;1&nbsp;∧&nbsp;<span class="id" type="var">Y</span>&nbsp;=&nbsp;2&nbsp;<span style='letter-spacing:-.4em;'>}</span>}
<div class="paragraph"> </div>

</div>
   （带 “<span class="inlinecode"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>></span>></span></span></span>” 的标记代表了使用 <span class="inlinecode"><span class="id" type="var">hoare_consequence_pre</span></span>。） 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Example</span> <span class="id" type="var">hoare_asgn_example4</span> :<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">True</span><span style='letter-spacing:-.4em;'>}</span>}<br/>
&nbsp;&nbsp;<span class="id" type="var">X</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> 1;; <span class="id" type="var">Y</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> 2<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">st</span> <span class="id" type="var">X</span> = 1 ∧ <span class="id" type="var">st</span> <span class="id" type="var">Y</span> = 2<span style='letter-spacing:-.4em;'>}</span>}.<br/>
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/>
</div>

<span class="proofbox">&#9744;</span> 
<div class="doc less-space">
<div class="paragraph"> </div>

<a name="lab66"></a><h4 class="section">练习：3 星, standard (swap_exercise)</h4>
 写一个 Imp 程序 <span class="inlinecode"><span class="id" type="var">c</span></span>，用来交换变量 <span class="inlinecode"><span class="id" type="var">X</span></span> 和 <span class="inlinecode"><span class="id" type="var">Y</span></span> 并且说明
    它符合如下规范：

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">X</span>&nbsp;≤&nbsp;<span class="id" type="var">Y</span><span style='letter-spacing:-.4em;'>}</span>}&nbsp;<span class="id" type="var">c</span>&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Y</span>&nbsp;≤&nbsp;<span class="id" type="var">X</span><span style='letter-spacing:-.4em;'>}</span>}
<div class="paragraph"> </div>

</div>
     你的证明不应该使用 <span class="inlinecode"><span class="id" type="tactic">unfold</span></span> <span class="inlinecode"><span class="id" type="var">hoare_triple</span></span>。
     （提示：记住赋值规则在“从后往前”，即从后置条件到前置条件应用时工作得最好。
     因此你的证明可以从程序的后面开始逐步往前进行。） 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Definition</span> <span class="id" type="var">swap_program</span> : <span class="id" type="var">com</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;将本行替换成&nbsp;":=&nbsp;_你的_定义_&nbsp;."&nbsp;*)</span>. <span class="id" type="var">Admitted</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">swap_exercise</span> :<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">st</span> <span class="id" type="var">X</span> ≤ <span class="id" type="var">st</span> <span class="id" type="var">Y</span><span style='letter-spacing:-.4em;'>}</span>}<br/>
&nbsp;&nbsp;<span class="id" type="var">swap_program</span><br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">st</span> <span class="id" type="var">Y</span> ≤ <span class="id" type="var">st</span> <span class="id" type="var">X</span><span style='letter-spacing:-.4em;'>}</span>}.<br/>
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/>
</div>

<span class="proofbox">&#9744;</span> 
<div class="doc less-space">
<div class="paragraph"> </div>

<a name="lab67"></a><h4 class="section">练习：3 星, standard (hoarestate1)</h4>
 解释为何下列命题无法被证明：

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='font-size:120%;'>&forall;</span>(<span class="id" type="var">a</span>&nbsp;:&nbsp;<span class="id" type="var">aexp</span>)&nbsp;(<span class="id" type="var">n</span>&nbsp;:&nbsp;<span class="id" type="var">nat</span>),<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="keyword">fun</span>&nbsp;<span class="id" type="var">st</span>&nbsp;⇒&nbsp;<span class="id" type="var">aeval</span>&nbsp;<span class="id" type="var">st</span>&nbsp;<span class="id" type="var">a</span>&nbsp;=&nbsp;<span class="id" type="var">n</span><span style='letter-spacing:-.4em;'>}</span>}<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;3;;&nbsp;<span class="id" type="var">Y</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;<span class="id" type="var">a</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="keyword">fun</span>&nbsp;<span class="id" type="var">st</span>&nbsp;⇒&nbsp;<span class="id" type="var">st</span>&nbsp;<span class="id" type="var">Y</span>&nbsp;=&nbsp;<span class="id" type="var">n</span><span style='letter-spacing:-.4em;'>}</span>}.
<div class="paragraph"> </div>

</div>

</div>
<div class="code code-tight">

<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span><br/><hr class='doublespaceincode'/>
<span class="comment">(*&nbsp;请勿修改下面这一行：&nbsp;*)</span><br/>
<span class="id" type="keyword">Definition</span> <span class="id" type="var">manual_grade_for_hoarestate1</span> : <span class="id" type="var">option</span> (<span class="id" type="var">nat</span>*<span class="id" type="var">string</span>) := <span class="id" type="var">None</span>.<br/>
</div>

<span class="proofbox">&#9744;</span> 

<div class="doc">
<a name="lab68"></a><h2 class="section">条件</h2>

<div class="paragraph"> </div>

 我们需要什么样的规则来推理条件命令呢？

<div class="paragraph"> </div>

    当然，如果断言 <span class="inlinecode"><span class="id" type="var">Q</span></span> 在两个分支执行后都成立，它就对整个条件命令成立。
    所以我们可以试着给出：
<center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{P<span style='letter-spacing:-.4em;'>}</span>}&nbsp;c<sub>1</sub>&nbsp;<span style='letter-spacing:-.4em;'>{</span>{Q<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td></td>
</td>
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{P<span style='letter-spacing:-.4em;'>}</span>}&nbsp;c<sub>2</sub>&nbsp;<span style='letter-spacing:-.4em;'>{</span>{Q<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td class="infrulenamecol" rowspan="3">
    &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{P<span style='letter-spacing:-.4em;'>}</span>}&nbsp;TEST&nbsp;b&nbsp;THEN&nbsp;c<sub>1</sub>&nbsp;ELSE&nbsp;c<sub>2</sub>&nbsp;<span style='letter-spacing:-.4em;'>{</span>{Q<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td></td>
</td>
</table></center>
<div class="paragraph"> </div>

 然而，这个规则太弱了。例如，用这个规则我们并不能推理出

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;<span class="id" type="var">True</span>&nbsp;<span style='letter-spacing:-.4em;'>}</span>}<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">TEST</span>&nbsp;<span class="id" type="var">X</span>&nbsp;=&nbsp;0<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">THEN</span>&nbsp;<span class="id" type="var">Y</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;2<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">ELSE</span>&nbsp;<span class="id" type="var">Y</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;<span class="id" type="var">X</span>&nbsp;+&nbsp;1<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">FI</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;<span class="id" type="var">X</span>&nbsp;≤&nbsp;<span class="id" type="var">Y</span>&nbsp;<span style='letter-spacing:-.4em;'>}</span>}
<div class="paragraph"> </div>

</div>
   因为这个规则并没有告诉我们在“THEN”和“ELSE”分支中赋值时的状态。
<div class="paragraph"> </div>

 不过我们还是可以表述得更精确。在“THEN”分支中，<span class="inlinecode"><span class="id" type="var">b</span></span> 化简为
    <span class="inlinecode"><span class="id" type="var">true</span></span>，而在“ELSE”分支中我们知道它化简为 <span class="inlinecode"><span class="id" type="var">false</span></span>。
    我们可以让这个信息作为 <span class="inlinecode"><span class="id" type="var">c<sub>1</sub></span></span> 和 <span class="inlinecode"><span class="id" type="var">c<sub>2</sub></span></span> 的假设出现可以让我们分别研究
    <span class="inlinecode"><span class="id" type="var">c<sub>1</sub></span></span> 和 <span class="inlinecode"><span class="id" type="var">c<sub>2</sub></span></span> 的行为（亦即它们为什么能导出后置条件 <span class="inlinecode"><span class="id" type="var">Q</span></span>）。
<div class="paragraph"> </div>

<center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{P&nbsp;∧&nbsp;&nbsp;&nbsp;b<span style='letter-spacing:-.4em;'>}</span>}&nbsp;c<sub>1</sub>&nbsp;<span style='letter-spacing:-.4em;'>{</span>{Q<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td></td>
</td>
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{P&nbsp;∧&nbsp;¬b<span style='letter-spacing:-.4em;'>}</span>}&nbsp;c<sub>2</sub>&nbsp;<span style='letter-spacing:-.4em;'>{</span>{Q<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td class="infrulenamecol" rowspan="3">
    (hoare_if) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{P<span style='letter-spacing:-.4em;'>}</span>}&nbsp;TEST&nbsp;b&nbsp;THEN&nbsp;c<sub>1</sub>&nbsp;ELSE&nbsp;c<sub>2</sub>&nbsp;FI&nbsp;<span style='letter-spacing:-.4em;'>{</span>{Q<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td></td>
</td>
</table></center>
<div class="paragraph"> </div>

 要形式化地解释这个规则，我们还需要做一点微小的工作。
    严格来说，我们写下的断言 <span class="inlinecode"><span class="id" type="var">P</span></span> <span class="inlinecode">∧</span> <span class="inlinecode"><span class="id" type="var">b</span></span>，是一个断言和一个布尔表达式的
    合取——也就是说，它并不能通过类型检查。为了让它正常工作，
    我们必须要把 <span class="inlinecode"><span class="id" type="var">b</span></span> “升格” 为一个断言。我们用 <span class="inlinecode"><span class="id" type="var">bassn</span></span> <span class="inlinecode"><span class="id" type="var">b</span></span> 来表示“
    <span class="inlinecode"><span class="id" type="var">b</span></span> 在给定的状态中化简到 <span class="inlinecode"><span class="id" type="var">true</span></span>”。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Definition</span> <span class="id" type="var">bassn</span> <span class="id" type="var">b</span> : <span class="id" type="var">Assertion</span> :=<br/>
&nbsp;&nbsp;<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ (<span class="id" type="var">beval</span> <span class="id" type="var">st</span> <span class="id" type="var">b</span> = <span class="id" type="var">true</span>).<br/>
</div>

<div class="doc">
下列是一些有关于 <span class="inlinecode"><span class="id" type="var">bassn</span></span> 的有用的引理：
</div>
<div class="code code-tight">

<span class="id" type="keyword">Lemma</span> <span class="id" type="var">bexp_eval_true</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">b</span> <span class="id" type="var">st</span>,<br/>
&nbsp;&nbsp;<span class="id" type="var">beval</span> <span class="id" type="var">st</span> <span class="id" type="var">b</span> = <span class="id" type="var">true</span> → (<span class="id" type="var">bassn</span> <span class="id" type="var">b</span>) <span class="id" type="var">st</span>.<br/>
<div class="togglescript" id="proofcontrol9" onclick="toggleDisplay('proof9');toggleDisplay('proofcontrol9')"><span class="show"></span></div>
<div class="proofscript" id="proof9" onclick="toggleDisplay('proof9');toggleDisplay('proofcontrol9')">
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">b</span> <span class="id" type="var">st</span> <span class="id" type="var">Hbe</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">unfold</span> <span class="id" type="var">bassn</span>. <span class="id" type="tactic">assumption</span>. <span class="id" type="keyword">Qed</span>.<br/>
</div>

<br/>
<span class="id" type="keyword">Lemma</span> <span class="id" type="var">bexp_eval_false</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">b</span> <span class="id" type="var">st</span>,<br/>
&nbsp;&nbsp;<span class="id" type="var">beval</span> <span class="id" type="var">st</span> <span class="id" type="var">b</span> = <span class="id" type="var">false</span> → ¬((<span class="id" type="var">bassn</span> <span class="id" type="var">b</span>) <span class="id" type="var">st</span>).<br/>
<div class="togglescript" id="proofcontrol10" onclick="toggleDisplay('proof10');toggleDisplay('proofcontrol10')"><span class="show"></span></div>
<div class="proofscript" id="proof10" onclick="toggleDisplay('proof10');toggleDisplay('proofcontrol10')">
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">b</span> <span class="id" type="var">st</span> <span class="id" type="var">Hbe</span> <span class="id" type="var">contra</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">unfold</span> <span class="id" type="var">bassn</span> <span class="id" type="keyword">in</span> <span class="id" type="var">contra</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> → <span class="id" type="var">contra</span> <span class="id" type="keyword">in</span> <span class="id" type="var">Hbe</span>. <span class="id" type="tactic">inversion</span> <span class="id" type="var">Hbe</span>. <span class="id" type="keyword">Qed</span>.<br/>
</div>
</div>

<div class="doc">
现在我们就可以形式化条件命令的证明规则，并且证明它的正确性。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Theorem</span> <span class="id" type="var">hoare_if</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">P</span> <span class="id" type="var">Q</span> <span class="id" type="var">b</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span>,<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">P</span> <span class="id" type="var">st</span> ∧ <span class="id" type="var">bassn</span> <span class="id" type="var">b</span> <span class="id" type="var">st</span><span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">c<sub>1</sub></span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Q</span><span style='letter-spacing:-.4em;'>}</span>} →<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">P</span> <span class="id" type="var">st</span> ∧ ¬(<span class="id" type="var">bassn</span> <span class="id" type="var">b</span> <span class="id" type="var">st</span>)<span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">c<sub>2</sub></span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Q</span><span style='letter-spacing:-.4em;'>}</span>} →<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">TEST</span> <span class="id" type="var">b</span> <span class="id" type="var">THEN</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">ELSE</span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">FI</span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Q</span><span style='letter-spacing:-.4em;'>}</span>}.<br/>
<div class="togglescript" id="proofcontrol11" onclick="toggleDisplay('proof11');toggleDisplay('proofcontrol11')"><span class="show"></span></div>
<div class="proofscript" id="proof11" onclick="toggleDisplay('proof11');toggleDisplay('proofcontrol11')">
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">P</span> <span class="id" type="var">Q</span> <span class="id" type="var">b</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">HTrue</span> <span class="id" type="var">HFalse</span> <span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">HE</span> <span class="id" type="var">HP</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">HE</span>; <span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;b&nbsp;是&nbsp;true&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> (<span class="id" type="var">HTrue</span> <span class="id" type="var">st</span> <span class="id" type="var">st'</span>).<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">split</span>. <span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">bexp_eval_true</span>. <span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;b&nbsp;是&nbsp;false&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> (<span class="id" type="var">HFalse</span> <span class="id" type="var">st</span> <span class="id" type="var">st'</span>).<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">split</span>. <span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">bexp_eval_false</span>. <span class="id" type="tactic">assumption</span>. <span class="id" type="keyword">Qed</span>.<br/>
</div>
</div>

<div class="doc">
<a name="lab69"></a><h3 class="section">例子</h3>

<div class="paragraph"> </div>

 下面是刚刚例子的形式化证明，我们用规则来证明程序符合规范。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Example</span> <span class="id" type="var">if_example</span> :<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">True</span><span style='letter-spacing:-.4em;'>}</span>}<br/>
&nbsp;&nbsp;<span class="id" type="var">TEST</span> <span class="id" type="var">X</span> = 0<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">THEN</span> <span class="id" type="var">Y</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> 2<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">ELSE</span> <span class="id" type="var">Y</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">X</span> + 1<br/>
&nbsp;&nbsp;<span class="id" type="var">FI</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">st</span> <span class="id" type="var">X</span> ≤ <span class="id" type="var">st</span> <span class="id" type="var">Y</span><span style='letter-spacing:-.4em;'>}</span>}.<br/>
<div class="togglescript" id="proofcontrol12" onclick="toggleDisplay('proof12');toggleDisplay('proofcontrol12')"><span class="show"></span></div>
<div class="proofscript" id="proof12" onclick="toggleDisplay('proof12');toggleDisplay('proofcontrol12')">
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;课上已完成&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">hoare_if</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;Then&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">hoare_consequence_pre</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">hoare_asgn</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">unfold</span> <span class="id" type="var">bassn</span>, <span class="id" type="var">assn_sub</span>, <span class="id" type="var">t_update</span>, <span class="id" type="var">assert_implies</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">simpl</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">st</span> [<span class="id" type="var">_</span> <span class="id" type="var">H</span>].<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">eqb_eq</span> <span class="id" type="keyword">in</span> <span class="id" type="var">H</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> <span class="id" type="var">H</span>. <span class="id" type="tactic">omega</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;Else&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">hoare_consequence_pre</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">hoare_asgn</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">unfold</span> <span class="id" type="var">assn_sub</span>, <span class="id" type="var">t_update</span>, <span class="id" type="var">assert_implies</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">simpl</span>; <span class="id" type="tactic">intros</span> <span class="id" type="var">st</span> <span class="id" type="var">_</span>. <span class="id" type="tactic">omega</span>.<br/>
<span class="id" type="keyword">Qed</span>.<br/>
</div>
</div>

<div class="doc">
<a name="lab70"></a><h4 class="section">练习：2 星, standard (if_minus_plus)</h4>
 用 <span class="inlinecode"><span class="id" type="var">hoare_if</span></span> 证明下面的三元组。不要使用 <span class="inlinecode"><span class="id" type="tactic">unfold</span></span> <span class="inlinecode"><span class="id" type="var">hoare_triple</span></span>。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Theorem</span> <span class="id" type="var">if_minus_plus</span> :<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">True</span><span style='letter-spacing:-.4em;'>}</span>}<br/>
&nbsp;&nbsp;<span class="id" type="var">TEST</span> <span class="id" type="var">X</span> ≤ <span class="id" type="var">Y</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">THEN</span> <span class="id" type="var">Z</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">Y</span> - <span class="id" type="var">X</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">ELSE</span> <span class="id" type="var">Y</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">X</span> + <span class="id" type="var">Z</span><br/>
&nbsp;&nbsp;<span class="id" type="var">FI</span><br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">st</span> <span class="id" type="var">Y</span> = <span class="id" type="var">st</span> <span class="id" type="var">X</span> + <span class="id" type="var">st</span> <span class="id" type="var">Z</span><span style='letter-spacing:-.4em;'>}</span>}.<br/>
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/>
</div>

<span class="proofbox">&#9744;</span> 

<div class="doc">
<a name="lab71"></a><h3 class="section">练习：单侧条件</h3>

<div class="paragraph"> </div>

<a name="lab72"></a><h4 class="section">练习：4 星, standard (if1_hoare)</h4>
 在这个练习中我们考虑对 Imp 加入形如 <span class="inlinecode"><span class="id" type="var">IF<sub>1</sub></span></span> <span class="inlinecode"><span class="id" type="var">b</span></span> <span class="inlinecode"><span class="id" type="var">THEN</span></span> <span class="inlinecode"><span class="id" type="var">c</span></span> <span class="inlinecode"><span class="id" type="var">FI</span></span> 的“单边条件”。
    这里 <span class="inlinecode"><span class="id" type="var">b</span></span> 是个布尔表达式而 <span class="inlinecode"><span class="id" type="var">c</span></span> 是一个命令。如果 <span class="inlinecode"><span class="id" type="var">b</span></span> 化简为 <span class="inlinecode"><span class="id" type="var">true</span></span>， <span class="inlinecode"><span class="id" type="var">c</span></span>
    就被执行，而如果 <span class="inlinecode"><span class="id" type="var">b</span></span> 化简为 <span class="inlinecode"><span class="id" type="var">false</span></span>， <span class="inlinecode"><span class="id" type="var">IF<sub>1</sub></span></span> <span class="inlinecode"><span class="id" type="var">b</span></span> <span class="inlinecode"><span class="id" type="var">THEN</span></span> <span class="inlinecode"><span class="id" type="var">c</span></span> <span class="inlinecode"><span class="id" type="var">FI</span></span> 就啥也不做。

<div class="paragraph"> </div>

    我们推荐你，在尝试之后的联系之前，先完成这个。因为它应该会让你对材料
    有更加完善的认知。
<div class="paragraph"> </div>

 第一步是引入之前出现的命令和记号，并且加入新的命令。（我们已经
    帮你弄好了。在这里用一个分离的模组来避免污染全局命名空间。）
</div>
<div class="code code-tight">

<span class="id" type="keyword">Module</span> <span class="id" type="var">If<sub>1</sub></span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Inductive</span> <span class="id" type="var">com</span> : <span class="id" type="keyword">Type</span> :=<br/>
&nbsp;&nbsp;| <span class="id" type="var">CSkip</span> : <span class="id" type="var">com</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">CAss</span> : <span class="id" type="var">string</span> → <span class="id" type="var">aexp</span> → <span class="id" type="var">com</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">CSeq</span> : <span class="id" type="var">com</span> → <span class="id" type="var">com</span> → <span class="id" type="var">com</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">CIf</span> : <span class="id" type="var">bexp</span> → <span class="id" type="var">com</span> → <span class="id" type="var">com</span> → <span class="id" type="var">com</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">CWhile</span> : <span class="id" type="var">bexp</span> → <span class="id" type="var">com</span> → <span class="id" type="var">com</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">CIf1</span> : <span class="id" type="var">bexp</span> → <span class="id" type="var">com</span> → <span class="id" type="var">com</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Notation</span> "'SKIP'" :=<br/>
&nbsp;&nbsp;<span class="id" type="var">CSkip</span> : <span class="id" type="var">imp_scope</span>.<br/>
<span class="id" type="keyword">Notation</span> "c<sub>1</sub> ;; c<sub>2</sub>" :=<br/>
&nbsp;&nbsp;(<span class="id" type="var">CSeq</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span>) (<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 80, <span class="id" type="var">right</span> <span class="id" type="var">associativity</span>) : <span class="id" type="var">imp_scope</span>.<br/>
<span class="id" type="keyword">Notation</span> "X '<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>' a" :=<br/>
&nbsp;&nbsp;(<span class="id" type="var">CAss</span> <span class="id" type="var">X</span> <span class="id" type="var">a</span>) (<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 60) : <span class="id" type="var">imp_scope</span>.<br/>
<span class="id" type="keyword">Notation</span> "'WHILE' b 'DO' c 'END'" :=<br/>
&nbsp;&nbsp;(<span class="id" type="var">CWhile</span> <span class="id" type="var">b</span> <span class="id" type="var">c</span>) (<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 80, <span class="id" type="var">right</span> <span class="id" type="var">associativity</span>) : <span class="id" type="var">imp_scope</span>.<br/>
<span class="id" type="keyword">Notation</span> "'TEST' e<sub>1</sub> 'THEN' e<sub>2</sub> 'ELSE' e<sub>3</sub> 'FI'" :=<br/>
&nbsp;&nbsp;(<span class="id" type="var">CIf</span> <span class="id" type="var">e<sub>1</sub></span> <span class="id" type="var">e<sub>2</sub></span> <span class="id" type="var">e<sub>3</sub></span>) (<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 80, <span class="id" type="var">right</span> <span class="id" type="var">associativity</span>) : <span class="id" type="var">imp_scope</span>.<br/>
<span class="id" type="keyword">Notation</span> "'IF<sub>1</sub>' b 'THEN' c 'FI'" :=<br/>
&nbsp;&nbsp;(<span class="id" type="var">CIf1</span> <span class="id" type="var">b</span> <span class="id" type="var">c</span>) (<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 80, <span class="id" type="var">right</span> <span class="id" type="var">associativity</span>) : <span class="id" type="var">imp_scope</span>.<br/>
</div>

<div class="doc">
接下来我们需要拓展求值规则以包含 <span class="inlinecode"><span class="id" type="var">IF<sub>1</sub></span></span> 的情形。我们把任务交给你……
    应该网 <span class="inlinecode"><span class="id" type="var">ceval</span></span> 中加入哪条（那些）命令来化简单边分支命令？
</div>
<div class="code code-tight">

<span class="id" type="keyword">Reserved Notation</span> "st '=[' c ']⇒' st'" (<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 40).<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Open</span> <span class="id" type="keyword">Scope</span> <span class="id" type="var">imp_scope</span>.<br/>
<span class="id" type="keyword">Inductive</span> <span class="id" type="var">ceval</span> : <span class="id" type="var">com</span> → <span class="id" type="var">state</span> → <span class="id" type="var">state</span> → <span class="id" type="keyword">Prop</span> :=<br/>
&nbsp;&nbsp;| <span class="id" type="var">E_Skip</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">SKIP</span> ]⇒ <span class="id" type="var">st</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">E_Ass</span>  : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">a<sub>1</sub></span> <span class="id" type="var">n</span> <span class="id" type="var">x</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">aeval</span> <span class="id" type="var">st</span> <span class="id" type="var">a<sub>1</sub></span> = <span class="id" type="var">n</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">x</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">a<sub>1</sub></span> ]⇒ (<span class="id" type="var">x</span> !<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> <span class="id" type="var">n</span> ; <span class="id" type="var">st</span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">E_Seq</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">st''</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span>  =[ <span class="id" type="var">c<sub>1</sub></span> ]⇒ <span class="id" type="var">st'</span>  →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st'</span> =[ <span class="id" type="var">c<sub>2</sub></span> ]⇒ <span class="id" type="var">st''</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span>  =[ <span class="id" type="var">c<sub>1</sub></span> ;; <span class="id" type="var">c<sub>2</sub></span> ]⇒ <span class="id" type="var">st''</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">E_IfTrue</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">b</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">beval</span> <span class="id" type="var">st</span> <span class="id" type="var">b</span> = <span class="id" type="var">true</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">c<sub>1</sub></span> ]⇒ <span class="id" type="var">st'</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">TEST</span> <span class="id" type="var">b</span> <span class="id" type="var">THEN</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">ELSE</span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">FI</span> ]⇒ <span class="id" type="var">st'</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">E_IfFalse</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">b</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">beval</span> <span class="id" type="var">st</span> <span class="id" type="var">b</span> = <span class="id" type="var">false</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">c<sub>2</sub></span> ]⇒ <span class="id" type="var">st'</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">TEST</span> <span class="id" type="var">b</span> <span class="id" type="var">THEN</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">ELSE</span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">FI</span> ]⇒ <span class="id" type="var">st'</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">E_WhileFalse</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">b</span> <span class="id" type="var">st</span> <span class="id" type="var">c</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">beval</span> <span class="id" type="var">st</span> <span class="id" type="var">b</span> = <span class="id" type="var">false</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">WHILE</span> <span class="id" type="var">b</span> <span class="id" type="var">DO</span> <span class="id" type="var">c</span> <span class="id" type="var">END</span> ]⇒ <span class="id" type="var">st</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">E_WhileTrue</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">st''</span> <span class="id" type="var">b</span> <span class="id" type="var">c</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">beval</span> <span class="id" type="var">st</span> <span class="id" type="var">b</span> = <span class="id" type="var">true</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span>  =[ <span class="id" type="var">c</span> ]⇒ <span class="id" type="var">st'</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st'</span> =[ <span class="id" type="var">WHILE</span> <span class="id" type="var">b</span> <span class="id" type="var">DO</span> <span class="id" type="var">c</span> <span class="id" type="var">END</span> ]⇒ <span class="id" type="var">st''</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span>  =[ <span class="id" type="var">WHILE</span> <span class="id" type="var">b</span> <span class="id" type="var">DO</span> <span class="id" type="var">c</span> <span class="id" type="var">END</span> ]⇒ <span class="id" type="var">st''</span><br/>
<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span><br/>
<br/>
&nbsp;&nbsp;<span class="id" type="keyword">where</span> "st '=[' c ']⇒' st'" := (<span class="id" type="var">ceval</span> <span class="id" type="var">c</span> <span class="id" type="var">st</span> <span class="id" type="var">st'</span>).<br/>
<span class="id" type="var">Close</span> <span class="id" type="keyword">Scope</span> <span class="id" type="var">imp_scope</span>.<br/>
</div>

<div class="doc">
现在我们把霍尔三元组的定义和记号重新写在这里。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Definition</span> <span class="id" type="var">hoare_triple</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">P</span> : <span class="id" type="var">Assertion</span>) (<span class="id" type="var">c</span> : <span class="id" type="var">com</span>) (<span class="id" type="var">Q</span> : <span class="id" type="var">Assertion</span>) : <span class="id" type="keyword">Prop</span> :=<br/>
&nbsp;&nbsp;<span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">st'</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">c</span> ]⇒ <span class="id" type="var">st'</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">P</span> <span class="id" type="var">st</span>  →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Q</span> <span class="id" type="var">st'</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Notation</span> "<span style='letter-spacing:-.4em;'>{</span>{ P <span style='letter-spacing:-.4em;'>}</span>}  c  <span style='letter-spacing:-.4em;'>{</span>{ Q <span style='letter-spacing:-.4em;'>}</span>}" := (<span class="id" type="var">hoare_triple</span> <span class="id" type="var">P</span> <span class="id" type="var">c</span> <span class="id" type="var">Q</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 90, <span class="id" type="var">c</span> <span class="id" type="tactic">at</span> <span class="id" type="var">next</span> <span class="id" type="var">level</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: <span class="id" type="var">hoare_spec_scope</span>.<br/>
</div>

<div class="doc">
最终你得证明一个定理 <span class="inlinecode"><span class="id" type="var">hoare_if<sub>1</sub></span></span>，指出一个关于单边条件语句的证明规则。
    你得试着尽可能让它既正确又精准。
</div>
<div class="code code-tight">

<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span><br/>
</div>

<div class="doc">
要拿到全部的分数，你还得证明一个定理 <span class="inlinecode"><span class="id" type="var">hoare_if1_good</span></span> 指出你的规则足够精细，
    能够证明下列的霍尔三元组是有效的：

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;<span class="id" type="var">X</span>&nbsp;+&nbsp;<span class="id" type="var">Y</span>&nbsp;=&nbsp;<span class="id" type="var">Z</span>&nbsp;<span style='letter-spacing:-.4em;'>}</span>}<br/>
&nbsp;&nbsp;<span class="id" type="var">IF<sub>1</sub></span>&nbsp;~(<span class="id" type="var">Y</span>&nbsp;=&nbsp;0)&nbsp;<span class="id" type="var">THEN</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;<span class="id" type="var">X</span>&nbsp;+&nbsp;<span class="id" type="var">Y</span><br/>
&nbsp;&nbsp;<span class="id" type="var">FI</span><br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;<span class="id" type="var">X</span>&nbsp;=&nbsp;<span class="id" type="var">Z</span>&nbsp;<span style='letter-spacing:-.4em;'>}</span>}
<div class="paragraph"> </div>

</div>

<div class="paragraph"> </div>

 Hint: 提示，你的证明会用到其它证明规则。因为我们开了个新模组，你得把你用到
    的那些都拷到这来。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Lemma</span> <span class="id" type="var">hoare_if1_good</span> :<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{ <span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">st</span> <span class="id" type="var">X</span> + <span class="id" type="var">st</span> <span class="id" type="var">Y</span> = <span class="id" type="var">st</span> <span class="id" type="var">Z</span> <span style='letter-spacing:-.4em;'>}</span>}<br/>
&nbsp;&nbsp;(<span class="id" type="var">IF<sub>1</sub></span> ~(<span class="id" type="var">Y</span> = 0) <span class="id" type="var">THEN</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">X</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">X</span> + <span class="id" type="var">Y</span><br/>
&nbsp;&nbsp;<span class="id" type="var">FI</span>)%<span class="id" type="var">imp</span><br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{ <span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">st</span> <span class="id" type="var">X</span> = <span class="id" type="var">st</span> <span class="id" type="var">Z</span> <span style='letter-spacing:-.4em;'>}</span>}.<br/>
<span class="id" type="keyword">Proof</span>. <span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">End</span> <span class="id" type="var">If<sub>1</sub></span>.<br/><hr class='doublespaceincode'/>
<span class="comment">(*&nbsp;请勿修改下面这一行：&nbsp;*)</span><br/>
<span class="id" type="keyword">Definition</span> <span class="id" type="var">manual_grade_for_if1_hoare</span> : <span class="id" type="var">option</span> (<span class="id" type="var">nat</span>*<span class="id" type="var">string</span>) := <span class="id" type="var">None</span>.<br/>
</div>

<span class="proofbox">&#9744;</span> 

<div class="doc">
<a name="lab73"></a><h2 class="section">循环</h2>

<div class="paragraph"> </div>

 最后，我们需要一个用来推理循环的规则。 
<div class="paragraph"> </div>

 假设我们有一个循环

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">WHILE</span>&nbsp;<span class="id" type="var">b</span>&nbsp;<span class="id" type="var">DO</span>&nbsp;<span class="id" type="var">c</span>&nbsp;<span class="id" type="var">END</span>
<div class="paragraph"> </div>

</div>
    我们希望找到一个前置条件 <span class="inlinecode"><span class="id" type="var">P</span></span> 和一个后置条件 <span class="inlinecode"><span class="id" type="var">Q</span></span> 满足使

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>}&nbsp;<span class="id" type="var">WHILE</span>&nbsp;<span class="id" type="var">b</span>&nbsp;<span class="id" type="var">DO</span>&nbsp;<span class="id" type="var">c</span>&nbsp;<span class="id" type="var">END</span>&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Q</span><span style='letter-spacing:-.4em;'>}</span>}
<div class="paragraph"> </div>

</div>
    成为一个有效的霍尔三元组。 
<div class="paragraph"> </div>

 首先，让我们考虑 <span class="inlinecode"><span class="id" type="var">b</span></span> 在开始的时候是 <span class="inlinecode"><span class="id" type="var">false</span></span> 的情况，
    也就是说，让我们假设这个循环的循环体根本不执行。在这种情形
    下，这个循环的行为类似于 <span class="inlinecode"><span class="id" type="var">SKIP</span></span>，所以我们可能可以试着先这样
    写：
<div class="paragraph"> </div>


<div class="paragraph"> </div>


<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>}&nbsp;<span class="id" type="var">WHILE</span>&nbsp;<span class="id" type="var">b</span>&nbsp;<span class="id" type="var">DO</span>&nbsp;<span class="id" type="var">c</span>&nbsp;<span class="id" type="var">END</span>&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>}.
<div class="paragraph"> </div>

</div>

<div class="paragraph"> </div>

 不过就像我们在上面对条件语句分析时那样，我们还会有一点附加
    的信息：除了 <span class="inlinecode"><span class="id" type="var">P</span></span> 成立以外，<span class="inlinecode"><span class="id" type="var">b</span></span> 会在执行完毕以后化简为 <span class="inlinecode"><span class="id" type="var">false</span></span>。
    所以，我们可以再添补一下后置条件： 
<div class="paragraph"> </div>


<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>}&nbsp;<span class="id" type="var">WHILE</span>&nbsp;<span class="id" type="var">b</span>&nbsp;<span class="id" type="var">DO</span>&nbsp;<span class="id" type="var">c</span>&nbsp;<span class="id" type="var">END</span>&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span>&nbsp;∧&nbsp;¬<span class="id" type="var">b</span><span style='letter-spacing:-.4em;'>}</span>}
<div class="paragraph"> </div>

</div>

<div class="paragraph"> </div>

 那么循环体被执行的情形呢？为了确保 <span class="inlinecode"><span class="id" type="var">P</span></span> 在循环最终退出
    的时候成立，我们当然需要保证命令 <span class="inlinecode"><span class="id" type="var">c</span></span> 执行后 <span class="inlinecode"><span class="id" type="var">P</span></span> 成立。
    进一步说，因为 <span class="inlinecode"><span class="id" type="var">P</span></span> 在 <span class="inlinecode"><span class="id" type="var">c</span></span> 第一次执行前成立，每次 <span class="inlinecode"><span class="id" type="var">c</span></span> 执行完成
    都会重新满足作为后置条件的 <span class="inlinecode"><span class="id" type="var">P</span></span>，我们可以假设 <span class="inlinecode"><span class="id" type="var">P</span></span> 在 <span class="inlinecode"><span class="id" type="var">c</span></span> 执行前
    就成立。总结为以下规则：
<div class="paragraph"> </div>

<center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{P<span style='letter-spacing:-.4em;'>}</span>}&nbsp;c&nbsp;<span style='letter-spacing:-.4em;'>{</span>{P<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td class="infrulenamecol" rowspan="3">
    &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{P<span style='letter-spacing:-.4em;'>}</span>}&nbsp;WHILE&nbsp;b&nbsp;DO&nbsp;c&nbsp;END&nbsp;<span style='letter-spacing:-.4em;'>{</span>{P&nbsp;∧&nbsp;¬b<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td></td>
</td>
</table></center> 这几乎就是我们想要的规则，不过它还有一点可以改进的地方：在循环体
    开始是的时候，我们不止知道 <span class="inlinecode"><span class="id" type="var">P</span></span> 成立，还有条件 <span class="inlinecode"><span class="id" type="var">b</span></span> 会在当前状态
    中化简为 <span class="inlinecode"><span class="id" type="var">true</span></span>。
<div class="paragraph"> </div>

 这给我们带来了一点额外的信息用来推论 <span class="inlinecode"><span class="id" type="var">c</span></span> （用来说明它结束时
    满足不变式）。 而这会将我们导向此规则的最终版本：
<center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{P&nbsp;∧&nbsp;b<span style='letter-spacing:-.4em;'>}</span>}&nbsp;c&nbsp;<span style='letter-spacing:-.4em;'>{</span>{P<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td class="infrulenamecol" rowspan="3">
    (hoare_while) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{P<span style='letter-spacing:-.4em;'>}</span>}&nbsp;WHILE&nbsp;b&nbsp;DO&nbsp;c&nbsp;END&nbsp;<span style='letter-spacing:-.4em;'>{</span>{P&nbsp;∧&nbsp;¬b<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td></td>
</td>
</table></center>    断言 <span class="inlinecode"><span class="id" type="var">P</span></span> 叫做<b>循环不变式（invariant of the loop）</b>。

</div>
<div class="code code-tight">

<span class="id" type="keyword">Theorem</span> <span class="id" type="var">hoare_while</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">P</span> <span class="id" type="var">b</span> <span class="id" type="var">c</span>,<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">P</span> <span class="id" type="var">st</span> ∧ <span class="id" type="var">bassn</span> <span class="id" type="var">b</span> <span class="id" type="var">st</span><span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">c</span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>} →<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">WHILE</span> <span class="id" type="var">b</span> <span class="id" type="var">DO</span> <span class="id" type="var">c</span> <span class="id" type="var">END</span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">P</span> <span class="id" type="var">st</span> ∧ ¬(<span class="id" type="var">bassn</span> <span class="id" type="var">b</span> <span class="id" type="var">st</span>)<span style='letter-spacing:-.4em;'>}</span>}.<br/>
<div class="togglescript" id="proofcontrol13" onclick="toggleDisplay('proof13');toggleDisplay('proofcontrol13')"><span class="show"></span></div>
<div class="proofscript" id="proof13" onclick="toggleDisplay('proof13');toggleDisplay('proofcontrol13')">
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">P</span> <span class="id" type="var">b</span> <span class="id" type="var">c</span> <span class="id" type="var">Hhoare</span> <span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">He</span> <span class="id" type="var">HP</span>.<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;像之前见到过的，我们需要对&nbsp;<span class="inlinecode"><span class="id" type="var">He</span></span>&nbsp;做归纳来推理。<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;因为，在“继续循环”的情形中，假设会是关于整个循环而不只是关于&nbsp;<span class="inlinecode"><span class="id" type="var">c</span></span>&nbsp;的。*)</span><br/>
&nbsp;&nbsp;<span class="id" type="var">remember</span> (<span class="id" type="var">WHILE</span> <span class="id" type="var">b</span> <span class="id" type="var">DO</span> <span class="id" type="var">c</span> <span class="id" type="var">END</span>)%<span class="id" type="var">imp</span> <span class="id" type="keyword">as</span> <span class="id" type="var">wcom</span> <span class="id" type="var">eqn</span>:<span class="id" type="var">Heqwcom</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">induction</span> <span class="id" type="var">He</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">try</span> (<span class="id" type="tactic">inversion</span> <span class="id" type="var">Heqwcom</span>); <span class="id" type="tactic">subst</span>; <span class="id" type="tactic">clear</span> <span class="id" type="var">Heqwcom</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;E_WhileFalse&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">split</span>. <span class="id" type="tactic">assumption</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">bexp_eval_false</span>. <span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;E_WhileTrue&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">IHHe2</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> (<span class="id" type="var">Hhoare</span> <span class="id" type="var">st</span> <span class="id" type="var">st'</span>). <span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">split</span>. <span class="id" type="tactic">assumption</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">bexp_eval_true</span>. <span class="id" type="tactic">assumption</span>.<br/>
<span class="id" type="keyword">Qed</span>.<br/>
</div>
</div>

<div class="doc">
令人费解的事情是，我们把断言 <span class="inlinecode"><span class="id" type="var">P</span></span> 叫做“循环不变式” 并不代表它只是由
    （上述问题中的）循环体所保证（也就是 <span class="inlinecode"><span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>}</span> <span class="inlinecode"><span class="id" type="var">c</span></span> <span class="inlinecode"><span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>}</span>，其中 <span class="inlinecode"><span class="id" type="var">c</span></span> 是循环体），
    而实际上 <span class="inlinecode"><span class="id" type="var">P</span></span> <b>加上循环条件为真</b>才是 <span class="inlinecode"><span class="id" type="var">c</span></span> 能够推出后置条件所
    需要的前置条件。

<div class="paragraph"> </div>

    这是略微弱化的（但十分重要）前提。例如，如果 <span class="inlinecode"><span class="id" type="var">P</span></span> 是断言 <span class="inlinecode"><span class="id" type="var">X</span></span> <span class="inlinecode">=</span> <span class="inlinecode">0</span>，那么
    <span class="inlinecode"><span class="id" type="var">P</span></span> <b>是</b>下述循环的不变式：

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">WHILE</span>&nbsp;<span class="id" type="var">X</span>&nbsp;=&nbsp;2&nbsp;<span class="id" type="var">DO</span>&nbsp;<span class="id" type="var">X</span>&nbsp;:=&nbsp;1&nbsp;<span class="id" type="var">END</span>
<div class="paragraph"> </div>

</div>
    即使它很明显<b>不是</b>只由循环体所导出。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Example</span> <span class="id" type="var">while_example</span> :<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">st</span> <span class="id" type="var">X</span> ≤ 3<span style='letter-spacing:-.4em;'>}</span>}<br/>
&nbsp;&nbsp;<span class="id" type="var">WHILE</span> <span class="id" type="var">X</span> ≤ 2<br/>
&nbsp;&nbsp;<span class="id" type="var">DO</span> <span class="id" type="var">X</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">X</span> + 1 <span class="id" type="var">END</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">st</span> <span class="id" type="var">X</span> = 3<span style='letter-spacing:-.4em;'>}</span>}.<br/>
<div class="togglescript" id="proofcontrol14" onclick="toggleDisplay('proof14');toggleDisplay('proofcontrol14')"><span class="show"></span></div>
<div class="proofscript" id="proof14" onclick="toggleDisplay('proof14');toggleDisplay('proofcontrol14')">
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">hoare_consequence_post</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">hoare_while</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">hoare_consequence_pre</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">hoare_asgn</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">unfold</span> <span class="id" type="var">bassn</span>, <span class="id" type="var">assn_sub</span>, <span class="id" type="var">assert_implies</span>, <span class="id" type="var">t_update</span>. <span class="id" type="tactic">simpl</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">st</span> [<span class="id" type="var">H<sub>1</sub></span> <span class="id" type="var">H<sub>2</sub></span>]. <span class="id" type="tactic">apply</span> <span class="id" type="var">leb_complete</span> <span class="id" type="keyword">in</span> <span class="id" type="var">H<sub>2</sub></span>. <span class="id" type="tactic">omega</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">unfold</span> <span class="id" type="var">bassn</span>, <span class="id" type="var">assert_implies</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">st</span> [<span class="id" type="var">Hle</span> <span class="id" type="var">Hb</span>].<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">simpl</span> <span class="id" type="keyword">in</span> <span class="id" type="var">Hb</span>. <span class="id" type="tactic">destruct</span> ((<span class="id" type="var">st</span> <span class="id" type="var">X</span>) &lt;=? 2) <span class="id" type="var">eqn</span> : <span class="id" type="var">Heqle</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">exfalso</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">Hb</span>; <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">leb_iff_conv</span> <span class="id" type="keyword">in</span> <span class="id" type="var">Heqle</span>. <span class="id" type="tactic">omega</span>.<br/>
<span class="id" type="keyword">Qed</span>.<br/>
</div>
</div>

<div class="doc">
我们可以使用 WHILE 规则来证明下列的霍尔三元组。 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Theorem</span> <span class="id" type="var">always_loop_hoare</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">P</span> <span class="id" type="var">Q</span>,<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">WHILE</span> <span class="id" type="var">true</span> <span class="id" type="var">DO</span> <span class="id" type="var">SKIP</span> <span class="id" type="var">END</span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Q</span><span style='letter-spacing:-.4em;'>}</span>}.<br/>
<div class="togglescript" id="proofcontrol15" onclick="toggleDisplay('proof15');toggleDisplay('proofcontrol15')"><span class="show"></span></div>
<div class="proofscript" id="proof15" onclick="toggleDisplay('proof15');toggleDisplay('proofcontrol15')">
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;课上已完成&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">P</span> <span class="id" type="var">Q</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">hoare_consequence_pre</span> <span class="id" type="keyword">with</span> (<span class="id" type="var">P'</span> := <span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> : <span class="id" type="var">state</span> ⇒ <span class="id" type="var">True</span>).<br/>
&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">hoare_consequence_post</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">hoare_while</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;循环体维持不变式&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">hoare_post_true</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">st</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">I</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;循环体和循环条件不成立可以导出后条件&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">simpl</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">st</span> [<span class="id" type="var">Hinv</span> <span class="id" type="var">Hguard</span>].<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">exfalso</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">Hguard</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;前条件可以导出不变式&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">st</span> <span class="id" type="var">H</span>. <span class="id" type="var">constructor</span>. <span class="id" type="keyword">Qed</span>.<br/>
</div>
</div>

<div class="doc">
这很显然，因为我们知道 <span class="inlinecode"><span class="id" type="var">hoare_triple</span></span> 的定义断言了仅当
    该命令停机时其后条件才成立。如果命令不停机，我们可以在后置条件中证明任何我们需要的
    东西。
<div class="paragraph"> </div>

 我们一般把那些只讨论当命令最终停机（而不证明它们确实停机）的
    证明规则叫做描述“部分（partial）”正确性的逻辑。我们也可以给出描述“完全（total）”
    正确性（也就是带有命令停机的假设）的证明规则。不过在这章里我们只介绍部分正确性。
</div>

<div class="doc">
<a name="lab74"></a><h3 class="section">练习：<span class="inlinecode"><span class="id" type="var">REPEAT</span></span></h3>

<div class="paragraph"> </div>

<a name="lab75"></a><h4 class="section">练习：4 星, advanced (hoare_repeat)</h4>
 在这个练习中，我们会往 Imp 里面加一种新的命令：<span class="inlinecode"><span class="id" type="var">REPEAT</span></span> c <span class="inlinecode"><span class="id" type="var">UNTIL</span></span> b <span class="inlinecode"><span class="id" type="var">END</span></span>。
    请你写出 <span class="inlinecode"><span class="id" type="var">REPEAT</span></span> 的求值规则，并且写一个关于它的霍尔逻辑证明规则。
    （回想在 <a href="https://coq-zh.github.io/SF-zh/lf-current/Auto.html"><span class="inlineref">Auto</span></a> 中给出的规则，试着自己把这个写出来，别偷看。）
</div>
<div class="code code-tight">

<span class="id" type="keyword">Module</span> <span class="id" type="var">RepeatExercise</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Inductive</span> <span class="id" type="var">com</span> : <span class="id" type="keyword">Type</span> :=<br/>
&nbsp;&nbsp;| <span class="id" type="var">CSkip</span> : <span class="id" type="var">com</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">CAsgn</span> : <span class="id" type="var">string</span> → <span class="id" type="var">aexp</span> → <span class="id" type="var">com</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">CSeq</span> : <span class="id" type="var">com</span> → <span class="id" type="var">com</span> → <span class="id" type="var">com</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">CIf</span> : <span class="id" type="var">bexp</span> → <span class="id" type="var">com</span> → <span class="id" type="var">com</span> → <span class="id" type="var">com</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">CWhile</span> : <span class="id" type="var">bexp</span> → <span class="id" type="var">com</span> → <span class="id" type="var">com</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">CRepeat</span> : <span class="id" type="var">com</span> → <span class="id" type="var">bexp</span> → <span class="id" type="var">com</span>.<br/>
</div>

<div class="doc">
<span class="inlinecode"><span class="id" type="var">REPEAT</span></span> 的行为类似于 <span class="inlinecode"><span class="id" type="var">WHILE</span></span>，除了它的循环条件是在循环体结束
    <b>后</b>检查的，并且只要循环条件是 <span class="inlinecode"><span class="id" type="var">false</span></span> 循环就会被执行。因为
    这样，循环体至少会被执行一次。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Notation</span> "'SKIP'" :=<br/>
&nbsp;&nbsp;<span class="id" type="var">CSkip</span>.<br/>
<span class="id" type="keyword">Notation</span> "c<sub>1</sub> ;; c<sub>2</sub>" :=<br/>
&nbsp;&nbsp;(<span class="id" type="var">CSeq</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span>) (<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 80, <span class="id" type="var">right</span> <span class="id" type="var">associativity</span>).<br/>
<span class="id" type="keyword">Notation</span> "X '<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>' a" :=<br/>
&nbsp;&nbsp;(<span class="id" type="var">CAsgn</span> <span class="id" type="var">X</span> <span class="id" type="var">a</span>) (<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 60).<br/>
<span class="id" type="keyword">Notation</span> "'WHILE' b 'DO' c 'END'" :=<br/>
&nbsp;&nbsp;(<span class="id" type="var">CWhile</span> <span class="id" type="var">b</span> <span class="id" type="var">c</span>) (<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 80, <span class="id" type="var">right</span> <span class="id" type="var">associativity</span>).<br/>
<span class="id" type="keyword">Notation</span> "'TEST' e<sub>1</sub> 'THEN' e<sub>2</sub> 'ELSE' e<sub>3</sub> 'FI'" :=<br/>
&nbsp;&nbsp;(<span class="id" type="var">CIf</span> <span class="id" type="var">e<sub>1</sub></span> <span class="id" type="var">e<sub>2</sub></span> <span class="id" type="var">e<sub>3</sub></span>) (<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 80, <span class="id" type="var">right</span> <span class="id" type="var">associativity</span>).<br/>
<span class="id" type="keyword">Notation</span> "'REPEAT' e<sub>1</sub> 'UNTIL' b<sub>2</sub> 'END'" :=<br/>
&nbsp;&nbsp;(<span class="id" type="var">CRepeat</span> <span class="id" type="var">e<sub>1</sub></span> <span class="id" type="var">b<sub>2</sub></span>) (<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 80, <span class="id" type="var">right</span> <span class="id" type="var">associativity</span>).<br/>
</div>

<div class="doc">
在下面为 <span class="inlinecode"><span class="id" type="var">ceval</span></span> 加入 <span class="inlinecode"><span class="id" type="var">REPEAT</span></span>。你可以把 <span class="inlinecode"><span class="id" type="var">WHILE</span></span> 的规则当作一个
    模板，不过注意 <span class="inlinecode"><span class="id" type="var">REPEAT</span></span> 的循环体至少要执行一次，并且循环会在条件
    为真的时候结束。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Reserved Notation</span> "st '=[' c ']⇒' st'" (<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 40).<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Inductive</span> <span class="id" type="var">ceval</span> : <span class="id" type="var">state</span> → <span class="id" type="var">com</span> → <span class="id" type="var">state</span> → <span class="id" type="keyword">Prop</span> :=<br/>
&nbsp;&nbsp;| <span class="id" type="var">E_Skip</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">SKIP</span> ]⇒ <span class="id" type="var">st</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">E_Ass</span>  : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">a<sub>1</sub></span> <span class="id" type="var">n</span> <span class="id" type="var">x</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">aeval</span> <span class="id" type="var">st</span> <span class="id" type="var">a<sub>1</sub></span> = <span class="id" type="var">n</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">x</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">a<sub>1</sub></span> ]⇒ (<span class="id" type="var">x</span> !<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> <span class="id" type="var">n</span> ; <span class="id" type="var">st</span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">E_Seq</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">st''</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span>  =[ <span class="id" type="var">c<sub>1</sub></span> ]⇒ <span class="id" type="var">st'</span>  →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st'</span> =[ <span class="id" type="var">c<sub>2</sub></span> ]⇒ <span class="id" type="var">st''</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span>  =[ <span class="id" type="var">c<sub>1</sub></span> ;; <span class="id" type="var">c<sub>2</sub></span> ]⇒ <span class="id" type="var">st''</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">E_IfTrue</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">b</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">beval</span> <span class="id" type="var">st</span> <span class="id" type="var">b</span> = <span class="id" type="var">true</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">c<sub>1</sub></span> ]⇒ <span class="id" type="var">st'</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">TEST</span> <span class="id" type="var">b</span> <span class="id" type="var">THEN</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">ELSE</span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">FI</span> ]⇒ <span class="id" type="var">st'</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">E_IfFalse</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">b</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">beval</span> <span class="id" type="var">st</span> <span class="id" type="var">b</span> = <span class="id" type="var">false</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">c<sub>2</sub></span> ]⇒ <span class="id" type="var">st'</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">TEST</span> <span class="id" type="var">b</span> <span class="id" type="var">THEN</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">ELSE</span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">FI</span> ]⇒ <span class="id" type="var">st'</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">E_WhileFalse</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">b</span> <span class="id" type="var">st</span> <span class="id" type="var">c</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">beval</span> <span class="id" type="var">st</span> <span class="id" type="var">b</span> = <span class="id" type="var">false</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">WHILE</span> <span class="id" type="var">b</span> <span class="id" type="var">DO</span> <span class="id" type="var">c</span> <span class="id" type="var">END</span> ]⇒ <span class="id" type="var">st</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">E_WhileTrue</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">st''</span> <span class="id" type="var">b</span> <span class="id" type="var">c</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">beval</span> <span class="id" type="var">st</span> <span class="id" type="var">b</span> = <span class="id" type="var">true</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span>  =[ <span class="id" type="var">c</span> ]⇒ <span class="id" type="var">st'</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st'</span> =[ <span class="id" type="var">WHILE</span> <span class="id" type="var">b</span> <span class="id" type="var">DO</span> <span class="id" type="var">c</span> <span class="id" type="var">END</span> ]⇒ <span class="id" type="var">st''</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span>  =[ <span class="id" type="var">WHILE</span> <span class="id" type="var">b</span> <span class="id" type="var">DO</span> <span class="id" type="var">c</span> <span class="id" type="var">END</span> ]⇒ <span class="id" type="var">st''</span><br/>
<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span><br/>
<br/>
<span class="id" type="keyword">where</span> "st '=[' c ']⇒' st'" := (<span class="id" type="var">ceval</span> <span class="id" type="var">st</span> <span class="id" type="var">c</span> <span class="id" type="var">st'</span>).<br/>
</div>

<div class="doc">
下面是一些之前出现的定义，我们把它重新写一遍它就会用新的 <span class="inlinecode"><span class="id" type="var">ceval</span></span>。 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Definition</span> <span class="id" type="var">hoare_triple</span> (<span class="id" type="var">P</span> : <span class="id" type="var">Assertion</span>) (<span class="id" type="var">c</span> : <span class="id" type="var">com</span>) (<span class="id" type="var">Q</span> : <span class="id" type="var">Assertion</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: <span class="id" type="keyword">Prop</span> :=<br/>
&nbsp;&nbsp;<span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">st'</span>, <span class="id" type="var">st</span> =[ <span class="id" type="var">c</span> ]⇒ <span class="id" type="var">st'</span> → <span class="id" type="var">P</span> <span class="id" type="var">st</span> → <span class="id" type="var">Q</span> <span class="id" type="var">st'</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Notation</span> "<span style='letter-spacing:-.4em;'>{</span>{ P <span style='letter-spacing:-.4em;'>}</span>}  c  <span style='letter-spacing:-.4em;'>{</span>{ Q <span style='letter-spacing:-.4em;'>}</span>}" :=<br/>
&nbsp;&nbsp;(<span class="id" type="var">hoare_triple</span> <span class="id" type="var">P</span> <span class="id" type="var">c</span> <span class="id" type="var">Q</span>) (<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 90, <span class="id" type="var">c</span> <span class="id" type="tactic">at</span> <span class="id" type="var">next</span> <span class="id" type="var">level</span>).<br/>
</div>

<div class="doc">
为了保证写出了正确的 <span class="inlinecode"><span class="id" type="var">REPEAT</span></span> 计算规则，请你证明 <span class="inlinecode"><span class="id" type="var">ex1_repeat</span></span>
    能够正常计算。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Definition</span> <span class="id" type="var">ex1_repeat</span> :=<br/>
&nbsp;&nbsp;<span class="id" type="var">REPEAT</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">X</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> 1;;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Y</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">Y</span> + 1<br/>
&nbsp;&nbsp;<span class="id" type="var">UNTIL</span> <span class="id" type="var">X</span> = 1 <span class="id" type="var">END</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">ex1_repeat_works</span> :<br/>
&nbsp;&nbsp;<span class="id" type="var">empty_st</span> =[ <span class="id" type="var">ex1_repeat</span> ]⇒ (<span class="id" type="var">Y</span> !<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> 1 ; <span class="id" type="var">X</span> !<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> 1).<br/>
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/>
</div>

<div class="doc">
现在写出并证明一个定理 <span class="inlinecode"><span class="id" type="var">hoare_repeat</span></span> 表达一个 <span class="inlinecode"><span class="id" type="tactic">repeat</span></span>
    命令的合理证明规则。你可以把 <span class="inlinecode"><span class="id" type="var">hoare_while</span></span> 当作一个模型，
    试着让你的规则尽可能地精确。 
</div>
<div class="code code-tight">

<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span><br/>
</div>

<div class="doc">
要拿到全部的分数，请确保（非正式即可）你的规则可以用来证明以下
    的霍尔三元组成立。

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;<span class="id" type="var">X</span>&nbsp;&gt;&nbsp;0&nbsp;<span style='letter-spacing:-.4em;'>}</span>}<br/>
&nbsp;&nbsp;<span class="id" type="var">REPEAT</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Y</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;<span class="id" type="var">X</span>;;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;<span class="id" type="var">X</span>&nbsp;-&nbsp;1<br/>
&nbsp;&nbsp;<span class="id" type="var">UNTIL</span>&nbsp;<span class="id" type="var">X</span>&nbsp;=&nbsp;0&nbsp;<span class="id" type="var">END</span><br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;<span class="id" type="var">X</span>&nbsp;=&nbsp;0&nbsp;∧&nbsp;<span class="id" type="var">Y</span>&nbsp;&gt;&nbsp;0&nbsp;<span style='letter-spacing:-.4em;'>}</span>}
<div class="paragraph"> </div>

</div>

</div>
<div class="code code-tight">

<span class="id" type="keyword">End</span> <span class="id" type="var">RepeatExercise</span>.<br/><hr class='doublespaceincode'/>
<span class="comment">(*&nbsp;请勿修改下面这一行：&nbsp;*)</span><br/>
<span class="id" type="keyword">Definition</span> <span class="id" type="var">manual_grade_for_hoare_repeat</span> : <span class="id" type="var">option</span> (<span class="id" type="var">nat</span>*<span class="id" type="var">string</span>) := <span class="id" type="var">None</span>.<br/>
</div>

<span class="proofbox">&#9744;</span> 

<div class="doc">
<a name="lab76"></a><h1 class="section">总结</h1>

<div class="paragraph"> </div>

 到此为止，我们引入了用来推理 Imp 程序的工具，霍尔逻辑。霍尔逻辑
    的证明规则有：
<center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">&nbsp;&nbsp;</td>
  <td class="infrulenamecol" rowspan="3">
    (hoare_asgn) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{Q&nbsp;[X&nbsp;<span class="nowrap"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span></span>&nbsp;a]<span style='letter-spacing:-.4em;'>}</span>}&nbsp;X<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>a&nbsp;<span style='letter-spacing:-.4em;'>{</span>{Q<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td></td>
</td>
</table></center><center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule">&nbsp;&nbsp;</td>
  <td class="infrulenamecol" rowspan="3">
    (hoare_skip) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{&nbsp;P&nbsp;<span style='letter-spacing:-.4em;'>}</span>}&nbsp;SKIP&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;P&nbsp;<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td></td>
</td>
</table></center><center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{&nbsp;P&nbsp;<span style='letter-spacing:-.4em;'>}</span>}&nbsp;c<sub>1</sub>&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;Q&nbsp;<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td></td>
</td>
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{&nbsp;Q&nbsp;<span style='letter-spacing:-.4em;'>}</span>}&nbsp;c<sub>2</sub>&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;R&nbsp;<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td class="infrulenamecol" rowspan="3">
    (hoare_seq) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{&nbsp;P&nbsp;<span style='letter-spacing:-.4em;'>}</span>}&nbsp;c<sub>1</sub>;;c<sub>2</sub>&nbsp;<span style='letter-spacing:-.4em;'>{</span>{&nbsp;R&nbsp;<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td></td>
</td>
</table></center><center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{P&nbsp;∧&nbsp;&nbsp;&nbsp;b<span style='letter-spacing:-.4em;'>}</span>}&nbsp;c<sub>1</sub>&nbsp;<span style='letter-spacing:-.4em;'>{</span>{Q<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td></td>
</td>
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{P&nbsp;∧&nbsp;¬b<span style='letter-spacing:-.4em;'>}</span>}&nbsp;c<sub>2</sub>&nbsp;<span style='letter-spacing:-.4em;'>{</span>{Q<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td class="infrulenamecol" rowspan="3">
    (hoare_if) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{P<span style='letter-spacing:-.4em;'>}</span>}&nbsp;TEST&nbsp;b&nbsp;THEN&nbsp;c<sub>1</sub>&nbsp;ELSE&nbsp;c<sub>2</sub>&nbsp;FI&nbsp;<span style='letter-spacing:-.4em;'>{</span>{Q<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td></td>
</td>
</table></center><center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{P&nbsp;∧&nbsp;b<span style='letter-spacing:-.4em;'>}</span>}&nbsp;c&nbsp;<span style='letter-spacing:-.4em;'>{</span>{P<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td class="infrulenamecol" rowspan="3">
    (hoare_while) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{P<span style='letter-spacing:-.4em;'>}</span>}&nbsp;WHILE&nbsp;b&nbsp;DO&nbsp;c&nbsp;END&nbsp;<span style='letter-spacing:-.4em;'>{</span>{P&nbsp;∧&nbsp;¬b<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td></td>
</td>
</table></center><center><table class="infrule">
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{P'<span style='letter-spacing:-.4em;'>}</span>}&nbsp;c&nbsp;<span style='letter-spacing:-.4em;'>{</span>{Q'<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td></td>
</td>
<tr class="infruleassumption">
  <td class="infrule">P&nbsp;<span class="nowrap"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>></span>></span></span></span>&nbsp;P'</td>
  <td></td>
</td>
<tr class="infruleassumption">
  <td class="infrule">Q'&nbsp;<span class="nowrap"><span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>></span>></span></span></span>&nbsp;Q</td>
  <td class="infrulenamecol" rowspan="3">
    (hoare_consequence) &nbsp;
  </td></tr>
<tr class="infrulemiddle">
  <td class="infrule"><hr /></td>
</tr>
<tr class="infruleassumption">
  <td class="infrule"><span style='letter-spacing:-.4em;'>{</span>{P<span style='letter-spacing:-.4em;'>}</span>}&nbsp;c&nbsp;<span style='letter-spacing:-.4em;'>{</span>{Q<span style='letter-spacing:-.4em;'>}</span>}</td>
  <td></td>
</td>
</table></center>    下一章中我们会看如何用这些规则证明程序满足它们行为的规范。 
</div>

<div class="doc">
<a name="lab77"></a><h1 class="section">附加练习</h1>

<div class="paragraph"> </div>

<a name="lab78"></a><h4 class="section">练习：3 星, standard (hoare_havoc)</h4>
 在这个练习中我们将会为一种 <span class="inlinecode"><span class="id" type="var">HAVOC</span></span> 命令实现证明规则，这个命令类似于
    <a href="Imp.html"><span class="inlineref">Imp</span></a> 中的 <span class="inlinecode"><span class="id" type="var">any</span></span> 表达式。

<div class="paragraph"> </div>

    首先我们把这些命令放在一个分离的模块里，并且把命令的语法和粗略语义
    写下来。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Module</span> <span class="id" type="var">Himp</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Inductive</span> <span class="id" type="var">com</span> : <span class="id" type="keyword">Type</span> :=<br/>
&nbsp;&nbsp;| <span class="id" type="var">CSkip</span> : <span class="id" type="var">com</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">CAsgn</span> : <span class="id" type="var">string</span> → <span class="id" type="var">aexp</span> → <span class="id" type="var">com</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">CSeq</span> : <span class="id" type="var">com</span> → <span class="id" type="var">com</span> → <span class="id" type="var">com</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">CIf</span> : <span class="id" type="var">bexp</span> → <span class="id" type="var">com</span> → <span class="id" type="var">com</span> → <span class="id" type="var">com</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">CWhile</span> : <span class="id" type="var">bexp</span> → <span class="id" type="var">com</span> → <span class="id" type="var">com</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">CHavoc</span> : <span class="id" type="var">string</span> → <span class="id" type="var">com</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Notation</span> "'SKIP'" :=<br/>
&nbsp;&nbsp;<span class="id" type="var">CSkip</span>.<br/>
<span class="id" type="keyword">Notation</span> "X '<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>' a" :=<br/>
&nbsp;&nbsp;(<span class="id" type="var">CAsgn</span> <span class="id" type="var">X</span> <span class="id" type="var">a</span>) (<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 60).<br/>
<span class="id" type="keyword">Notation</span> "c<sub>1</sub> ;; c<sub>2</sub>" :=<br/>
&nbsp;&nbsp;(<span class="id" type="var">CSeq</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span>) (<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 80, <span class="id" type="var">right</span> <span class="id" type="var">associativity</span>).<br/>
<span class="id" type="keyword">Notation</span> "'WHILE' b 'DO' c 'END'" :=<br/>
&nbsp;&nbsp;(<span class="id" type="var">CWhile</span> <span class="id" type="var">b</span> <span class="id" type="var">c</span>) (<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 80, <span class="id" type="var">right</span> <span class="id" type="var">associativity</span>).<br/>
<span class="id" type="keyword">Notation</span> "'TEST' e<sub>1</sub> 'THEN' e<sub>2</sub> 'ELSE' e<sub>3</sub> 'FI'" :=<br/>
&nbsp;&nbsp;(<span class="id" type="var">CIf</span> <span class="id" type="var">e<sub>1</sub></span> <span class="id" type="var">e<sub>2</sub></span> <span class="id" type="var">e<sub>3</sub></span>) (<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 80, <span class="id" type="var">right</span> <span class="id" type="var">associativity</span>).<br/>
<span class="id" type="keyword">Notation</span> "'HAVOC' X" := (<span class="id" type="var">CHavoc</span> <span class="id" type="var">X</span>) (<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 60).<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Reserved Notation</span> "st '=[' c ']⇒' st'" (<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 40).<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Inductive</span> <span class="id" type="var">ceval</span> : <span class="id" type="var">com</span> → <span class="id" type="var">state</span> → <span class="id" type="var">state</span> → <span class="id" type="keyword">Prop</span> :=<br/>
&nbsp;&nbsp;| <span class="id" type="var">E_Skip</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">SKIP</span> ]⇒ <span class="id" type="var">st</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">E_Ass</span>  : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">a<sub>1</sub></span> <span class="id" type="var">n</span> <span class="id" type="var">x</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">aeval</span> <span class="id" type="var">st</span> <span class="id" type="var">a<sub>1</sub></span> = <span class="id" type="var">n</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">x</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">a<sub>1</sub></span> ]⇒ (<span class="id" type="var">x</span> !<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> <span class="id" type="var">n</span> ; <span class="id" type="var">st</span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">E_Seq</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">st''</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span>  =[ <span class="id" type="var">c<sub>1</sub></span> ]⇒ <span class="id" type="var">st'</span>  →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st'</span> =[ <span class="id" type="var">c<sub>2</sub></span> ]⇒ <span class="id" type="var">st''</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span>  =[ <span class="id" type="var">c<sub>1</sub></span> ;; <span class="id" type="var">c<sub>2</sub></span> ]⇒ <span class="id" type="var">st''</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">E_IfTrue</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">b</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">beval</span> <span class="id" type="var">st</span> <span class="id" type="var">b</span> = <span class="id" type="var">true</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">c<sub>1</sub></span> ]⇒ <span class="id" type="var">st'</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">TEST</span> <span class="id" type="var">b</span> <span class="id" type="var">THEN</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">ELSE</span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">FI</span> ]⇒ <span class="id" type="var">st'</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">E_IfFalse</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">b</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">beval</span> <span class="id" type="var">st</span> <span class="id" type="var">b</span> = <span class="id" type="var">false</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">c<sub>2</sub></span> ]⇒ <span class="id" type="var">st'</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">TEST</span> <span class="id" type="var">b</span> <span class="id" type="var">THEN</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">ELSE</span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">FI</span> ]⇒ <span class="id" type="var">st'</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">E_WhileFalse</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">b</span> <span class="id" type="var">st</span> <span class="id" type="var">c</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">beval</span> <span class="id" type="var">st</span> <span class="id" type="var">b</span> = <span class="id" type="var">false</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">WHILE</span> <span class="id" type="var">b</span> <span class="id" type="var">DO</span> <span class="id" type="var">c</span> <span class="id" type="var">END</span> ]⇒ <span class="id" type="var">st</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">E_WhileTrue</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">st''</span> <span class="id" type="var">b</span> <span class="id" type="var">c</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">beval</span> <span class="id" type="var">st</span> <span class="id" type="var">b</span> = <span class="id" type="var">true</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span>  =[ <span class="id" type="var">c</span> ]⇒ <span class="id" type="var">st'</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st'</span> =[ <span class="id" type="var">WHILE</span> <span class="id" type="var">b</span> <span class="id" type="var">DO</span> <span class="id" type="var">c</span> <span class="id" type="var">END</span> ]⇒ <span class="id" type="var">st''</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span>  =[ <span class="id" type="var">WHILE</span> <span class="id" type="var">b</span> <span class="id" type="var">DO</span> <span class="id" type="var">c</span> <span class="id" type="var">END</span> ]⇒ <span class="id" type="var">st''</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">E_Havoc</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">X</span> <span class="id" type="var">n</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">HAVOC</span> <span class="id" type="var">X</span> ]⇒ (<span class="id" type="var">X</span> !<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> <span class="id" type="var">n</span> ; <span class="id" type="var">st</span>)<br/>
<br/>
<span class="id" type="keyword">where</span> "st '=[' c ']⇒' st'" := (<span class="id" type="var">ceval</span> <span class="id" type="var">c</span> <span class="id" type="var">st</span> <span class="id" type="var">st'</span>).<br/>
</div>

<div class="doc">
对霍尔三元组的定义和之前完全一致。 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Definition</span> <span class="id" type="var">hoare_triple</span> (<span class="id" type="var">P</span>:<span class="id" type="var">Assertion</span>) (<span class="id" type="var">c</span>:<span class="id" type="var">com</span>) (<span class="id" type="var">Q</span>:<span class="id" type="var">Assertion</span>) : <span class="id" type="keyword">Prop</span> :=<br/>
&nbsp;&nbsp;<span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">st'</span>, <span class="id" type="var">st</span> =[ <span class="id" type="var">c</span> ]⇒ <span class="id" type="var">st'</span> → <span class="id" type="var">P</span> <span class="id" type="var">st</span> → <span class="id" type="var">Q</span> <span class="id" type="var">st'</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Notation</span> "<span style='letter-spacing:-.4em;'>{</span>{ P <span style='letter-spacing:-.4em;'>}</span>}  c  <span style='letter-spacing:-.4em;'>{</span>{ Q <span style='letter-spacing:-.4em;'>}</span>}" := (<span class="id" type="var">hoare_triple</span> <span class="id" type="var">P</span> <span class="id" type="var">c</span> <span class="id" type="var">Q</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 90, <span class="id" type="var">c</span> <span class="id" type="tactic">at</span> <span class="id" type="var">next</span> <span class="id" type="var">level</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: <span class="id" type="var">hoare_spec_scope</span>.<br/>
</div>

<div class="doc">
请通过定义 <span class="inlinecode"><span class="id" type="var">havoc_pre</span></span> 来创建一个关于 <span class="inlinecode"><span class="id" type="var">HAVOC</span></span> 的证明规则，并
    证明此规则是正确的。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Definition</span> <span class="id" type="var">havoc_pre</span> (<span class="id" type="var">X</span> : <span class="id" type="var">string</span>) (<span class="id" type="var">Q</span> : <span class="id" type="var">Assertion</span>) : <span class="id" type="var">Assertion</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;将本行替换成&nbsp;":=&nbsp;_你的_定义_&nbsp;."&nbsp;*)</span>. <span class="id" type="var">Admitted</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">hoare_havoc</span> : <span style='font-size:120%;'>&forall;</span>(<span class="id" type="var">Q</span> : <span class="id" type="var">Assertion</span>) (<span class="id" type="var">X</span> : <span class="id" type="var">string</span>),<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{ <span class="id" type="var">havoc_pre</span> <span class="id" type="var">X</span> <span class="id" type="var">Q</span> <span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">HAVOC</span> <span class="id" type="var">X</span> <span style='letter-spacing:-.4em;'>{</span>{ <span class="id" type="var">Q</span> <span style='letter-spacing:-.4em;'>}</span>}.<br/>
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">End</span> <span class="id" type="var">Himp</span>.<br/>
</div>

<span class="proofbox">&#9744;</span> 
<div class="doc less-space">
<div class="paragraph"> </div>

<a name="lab79"></a><h4 class="section">练习：4 星, standard, optional (assert_vs_assume)</h4>

</div>
<div class="code code-space">

<br/>
<span class="id" type="keyword">Module</span> <span class="id" type="var">HoareAssertAssume</span>.<br/>
</div>

<div class="doc">
 在这个练习中我们会对 Imp 加入语句 <span class="inlinecode"><span class="id" type="var">ASSERT</span></span> 和 <span class="inlinecode"><span class="id" type="var">ASSUME</span></span>。这两个命令
     都是用来指出某个布尔表达式应该在任何一次程序运行到这里的时候都为真。
     但是它们有下列区别：

<div class="paragraph"> </div>

<ul class="doclist">
<li> 如果 <span class="inlinecode"><span class="id" type="var">ASSERT</span></span> 失败了，程序就会进入错误状态并且退出。

<div class="paragraph"> </div>


</li>
<li> 如果 <span class="inlinecode"><span class="id" type="var">ASSUME</span></span> 失败了，程序就不能运行。换句话说这段程序会卡住，没有
      最终状态。

</li>
</ul>
    新的一系列命令是：
</div>
<div class="code code-tight">

<span class="id" type="keyword">Inductive</span> <span class="id" type="var">com</span> : <span class="id" type="keyword">Type</span> :=<br/>
&nbsp;&nbsp;| <span class="id" type="var">CSkip</span> : <span class="id" type="var">com</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">CAss</span> : <span class="id" type="var">string</span> → <span class="id" type="var">aexp</span> → <span class="id" type="var">com</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">CSeq</span> : <span class="id" type="var">com</span> → <span class="id" type="var">com</span> → <span class="id" type="var">com</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">CIf</span> : <span class="id" type="var">bexp</span> → <span class="id" type="var">com</span> → <span class="id" type="var">com</span> → <span class="id" type="var">com</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">CWhile</span> : <span class="id" type="var">bexp</span> → <span class="id" type="var">com</span> → <span class="id" type="var">com</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">CAssert</span> : <span class="id" type="var">bexp</span> → <span class="id" type="var">com</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">CAssume</span> : <span class="id" type="var">bexp</span> → <span class="id" type="var">com</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Notation</span> "'SKIP'" :=<br/>
&nbsp;&nbsp;<span class="id" type="var">CSkip</span>.<br/>
<span class="id" type="keyword">Notation</span> "x '<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>' a" :=<br/>
&nbsp;&nbsp;(<span class="id" type="var">CAss</span> <span class="id" type="var">x</span> <span class="id" type="var">a</span>) (<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 60).<br/>
<span class="id" type="keyword">Notation</span> "c<sub>1</sub> ;; c<sub>2</sub>" :=<br/>
&nbsp;&nbsp;(<span class="id" type="var">CSeq</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span>) (<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 80, <span class="id" type="var">right</span> <span class="id" type="var">associativity</span>).<br/>
<span class="id" type="keyword">Notation</span> "'WHILE' b 'DO' c 'END'" :=<br/>
&nbsp;&nbsp;(<span class="id" type="var">CWhile</span> <span class="id" type="var">b</span> <span class="id" type="var">c</span>) (<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 80, <span class="id" type="var">right</span> <span class="id" type="var">associativity</span>).<br/>
<span class="id" type="keyword">Notation</span> "'TEST' c<sub>1</sub> 'THEN' c<sub>2</sub> 'ELSE' c<sub>3</sub> 'FI'" :=<br/>
&nbsp;&nbsp;(<span class="id" type="var">CIf</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">c<sub>3</sub></span>) (<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 80, <span class="id" type="var">right</span> <span class="id" type="var">associativity</span>).<br/>
<span class="id" type="keyword">Notation</span> "'ASSERT' b" :=<br/>
&nbsp;&nbsp;(<span class="id" type="var">CAssert</span> <span class="id" type="var">b</span>) (<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 60).<br/>
<span class="id" type="keyword">Notation</span> "'ASSUME' b" :=<br/>
&nbsp;&nbsp;(<span class="id" type="var">CAssume</span> <span class="id" type="var">b</span>) (<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 60).<br/>
</div>

<div class="doc">
要定义 <span class="inlinecode"><span class="id" type="var">ASSERT</span></span> 和 <span class="inlinecode"><span class="id" type="var">ASSUME</span></span> 的行为，我们必须要加入一个表示错误
    状态的记号，它指出某个 <span class="inlinecode"><span class="id" type="var">ASSERT</span></span> 失败了。我们修改一下 <span class="inlinecode"><span class="id" type="var">ceval</span></span>
    规则，让它是开始状态和“结束状态或者是 <span class="inlinecode"><span class="id" type="var">error</span></span>”的关系。<span class="inlinecode"><span class="id" type="var">result</span></span>
    类型是程序结束时的值，要么是 <span class="inlinecode"><span class="id" type="var">state</span></span> 要么是 <span class="inlinecode"><span class="id" type="var">error</span></span>。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Inductive</span> <span class="id" type="var">result</span> : <span class="id" type="keyword">Type</span> :=<br/>
&nbsp;&nbsp;| <span class="id" type="var">RNormal</span> : <span class="id" type="var">state</span> → <span class="id" type="var">result</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">RError</span> : <span class="id" type="var">result</span>.<br/>
</div>

<div class="doc">
现在我们可以给出新语言的 <span class="inlinecode"><span class="id" type="var">ceval</span></span> 了。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Inductive</span> <span class="id" type="var">ceval</span> : <span class="id" type="var">com</span> → <span class="id" type="var">state</span> → <span class="id" type="var">result</span> → <span class="id" type="keyword">Prop</span> :=<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;稍加修改的旧有规则&nbsp;*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">E_Skip</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">SKIP</span> ]⇒ <span class="id" type="var">RNormal</span> <span class="id" type="var">st</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">E_Ass</span>  : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">a<sub>1</sub></span> <span class="id" type="var">n</span> <span class="id" type="var">x</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">aeval</span> <span class="id" type="var">st</span> <span class="id" type="var">a<sub>1</sub></span> = <span class="id" type="var">n</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">x</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">a<sub>1</sub></span> ]⇒ <span class="id" type="var">RNormal</span> (<span class="id" type="var">x</span> !<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> <span class="id" type="var">n</span> ; <span class="id" type="var">st</span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">E_SeqNormal</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">r</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span>  =[ <span class="id" type="var">c<sub>1</sub></span> ]⇒ <span class="id" type="var">RNormal</span> <span class="id" type="var">st'</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st'</span> =[ <span class="id" type="var">c<sub>2</sub></span> ]⇒ <span class="id" type="var">r</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span>  =[ <span class="id" type="var">c<sub>1</sub></span> ;; <span class="id" type="var">c<sub>2</sub></span> ]⇒ <span class="id" type="var">r</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">E_SeqError</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">st</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">c<sub>1</sub></span> ]⇒ <span class="id" type="var">RError</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">c<sub>1</sub></span> ;; <span class="id" type="var">c<sub>2</sub></span> ]⇒ <span class="id" type="var">RError</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">E_IfTrue</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">r</span> <span class="id" type="var">b</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">beval</span> <span class="id" type="var">st</span> <span class="id" type="var">b</span> = <span class="id" type="var">true</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">c<sub>1</sub></span> ]⇒ <span class="id" type="var">r</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">TEST</span> <span class="id" type="var">b</span> <span class="id" type="var">THEN</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">ELSE</span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">FI</span> ]⇒ <span class="id" type="var">r</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">E_IfFalse</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">r</span> <span class="id" type="var">b</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">beval</span> <span class="id" type="var">st</span> <span class="id" type="var">b</span> = <span class="id" type="var">false</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">c<sub>2</sub></span> ]⇒ <span class="id" type="var">r</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">TEST</span> <span class="id" type="var">b</span> <span class="id" type="var">THEN</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">ELSE</span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">FI</span> ]⇒ <span class="id" type="var">r</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">E_WhileFalse</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">b</span> <span class="id" type="var">st</span> <span class="id" type="var">c</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">beval</span> <span class="id" type="var">st</span> <span class="id" type="var">b</span> = <span class="id" type="var">false</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">WHILE</span> <span class="id" type="var">b</span> <span class="id" type="var">DO</span> <span class="id" type="var">c</span> <span class="id" type="var">END</span> ]⇒ <span class="id" type="var">RNormal</span> <span class="id" type="var">st</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">E_WhileTrueNormal</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">r</span> <span class="id" type="var">b</span> <span class="id" type="var">c</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">beval</span> <span class="id" type="var">st</span> <span class="id" type="var">b</span> = <span class="id" type="var">true</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span>  =[ <span class="id" type="var">c</span> ]⇒ <span class="id" type="var">RNormal</span> <span class="id" type="var">st'</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st'</span> =[ <span class="id" type="var">WHILE</span> <span class="id" type="var">b</span> <span class="id" type="var">DO</span> <span class="id" type="var">c</span> <span class="id" type="var">END</span> ]⇒ <span class="id" type="var">r</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span>  =[ <span class="id" type="var">WHILE</span> <span class="id" type="var">b</span> <span class="id" type="var">DO</span> <span class="id" type="var">c</span> <span class="id" type="var">END</span> ]⇒ <span class="id" type="var">r</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">E_WhileTrueError</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">b</span> <span class="id" type="var">c</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">beval</span> <span class="id" type="var">st</span> <span class="id" type="var">b</span> = <span class="id" type="var">true</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">c</span> ]⇒ <span class="id" type="var">RError</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">WHILE</span> <span class="id" type="var">b</span> <span class="id" type="var">DO</span> <span class="id" type="var">c</span> <span class="id" type="var">END</span> ]⇒ <span class="id" type="var">RError</span><br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;Assert&nbsp;和&nbsp;Assume&nbsp;的规则&nbsp;*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">E_AssertTrue</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">b</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">beval</span> <span class="id" type="var">st</span> <span class="id" type="var">b</span> = <span class="id" type="var">true</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">ASSERT</span> <span class="id" type="var">b</span> ]⇒ <span class="id" type="var">RNormal</span> <span class="id" type="var">st</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">E_AssertFalse</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">b</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">beval</span> <span class="id" type="var">st</span> <span class="id" type="var">b</span> = <span class="id" type="var">false</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">ASSERT</span> <span class="id" type="var">b</span> ]⇒ <span class="id" type="var">RError</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">E_Assume</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">b</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">beval</span> <span class="id" type="var">st</span> <span class="id" type="var">b</span> = <span class="id" type="var">true</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">ASSUME</span> <span class="id" type="var">b</span> ]⇒ <span class="id" type="var">RNormal</span> <span class="id" type="var">st</span><br/>
<br/>
<span class="id" type="keyword">where</span> "st '=[' c ']⇒' r" := (<span class="id" type="var">ceval</span> <span class="id" type="var">c</span> <span class="id" type="var">st</span> <span class="id" type="var">r</span>).<br/>
</div>

<div class="doc">
我们重新定义霍尔三元组：现在，<span class="inlinecode"><span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>}</span> <span class="inlinecode"><span class="id" type="var">c</span></span> <span class="inlinecode"><span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Q</span><span style='letter-spacing:-.4em;'>}</span>}</span> 的意思是，
    当 <span class="inlinecode"><span class="id" type="var">c</span></span> 在一个满足 <span class="inlinecode"><span class="id" type="var">P</span></span> 的状态中启动并且停机在一个状态 <span class="inlinecode"><span class="id" type="var">r</span></span>，那么 <span class="inlinecode"><span class="id" type="var">r</span></span>
    不是错误并且满足 <span class="inlinecode"><span class="id" type="var">Q</span></span>。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Definition</span> <span class="id" type="var">hoare_triple</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">P</span> : <span class="id" type="var">Assertion</span>) (<span class="id" type="var">c</span> : <span class="id" type="var">com</span>) (<span class="id" type="var">Q</span> : <span class="id" type="var">Assertion</span>) : <span class="id" type="keyword">Prop</span> :=<br/>
&nbsp;&nbsp;<span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">r</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">c</span> ]⇒ <span class="id" type="var">r</span>  → <span class="id" type="var">P</span> <span class="id" type="var">st</span>  →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span style='font-size:120%;'>&exist;</span><span class="id" type="var">st'</span>, <span class="id" type="var">r</span> = <span class="id" type="var">RNormal</span> <span class="id" type="var">st'</span> ∧ <span class="id" type="var">Q</span> <span class="id" type="var">st'</span>).<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Notation</span> "<span style='letter-spacing:-.4em;'>{</span>{ P <span style='letter-spacing:-.4em;'>}</span>}  c  <span style='letter-spacing:-.4em;'>{</span>{ Q <span style='letter-spacing:-.4em;'>}</span>}" :=<br/>
&nbsp;&nbsp;(<span class="id" type="var">hoare_triple</span> <span class="id" type="var">P</span> <span class="id" type="var">c</span> <span class="id" type="var">Q</span>) (<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 90, <span class="id" type="var">c</span> <span class="id" type="tactic">at</span> <span class="id" type="var">next</span> <span class="id" type="var">level</span>)<br/>
&nbsp;&nbsp;: <span class="id" type="var">hoare_spec_scope</span>.<br/>
</div>

<div class="doc">
为了测试你对这个修改的理解是否正确，请给出一组前置条件和后置条件，
    它们可以被 <span class="inlinecode"><span class="id" type="var">ASSUME</span></span> 语句导出却不能被 <span class="inlinecode"><span class="id" type="var">ASSERT</span></span> 导出。然后证明任何关于
    <span class="inlinecode"><span class="id" type="var">ASSERT</span></span> 的三元组换成 <span class="inlinecode"><span class="id" type="var">ASSUME</span></span> 也是正确的。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Theorem</span> <span class="id" type="var">assert_assume_differ</span> : <span style='font-size:120%;'>&exist;</span><span class="id" type="var">P</span> <span class="id" type="var">b</span> <span class="id" type="var">Q</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">ASSUME</span> <span class="id" type="var">b</span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Q</span><span style='letter-spacing:-.4em;'>}</span>})<br/>
&nbsp;&nbsp;∧ ¬(<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">ASSERT</span> <span class="id" type="var">b</span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Q</span><span style='letter-spacing:-.4em;'>}</span>}).<br/>
<span class="id" type="keyword">Proof</span>.<br/>
<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">assert_implies_assume</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">P</span> <span class="id" type="var">b</span> <span class="id" type="var">Q</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">ASSERT</span> <span class="id" type="var">b</span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Q</span><span style='letter-spacing:-.4em;'>}</span>})<br/>
&nbsp;&nbsp;→ (<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">ASSUME</span> <span class="id" type="var">b</span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Q</span><span style='letter-spacing:-.4em;'>}</span>}).<br/>
<span class="id" type="keyword">Proof</span>.<br/>
<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/>
</div>

<div class="doc">
你的任务是为 <span class="inlinecode"><span class="id" type="var">ASSERT</span></span> 和 <span class="inlinecode"><span class="id" type="var">ASSUME</span></span> 创建霍尔规则，并且用它们证明
    一个小程序是正确的。把你的规则起名为 <span class="inlinecode"><span class="id" type="var">hoare_assert</span></span> 和 <span class="inlinecode"><span class="id" type="var">hoare_assume</span></span>。

<div class="paragraph"> </div>

    为了你方便点，我们把新语义上的那些旧有的霍尔规则帮你证明好了。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Theorem</span> <span class="id" type="var">hoare_asgn</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">Q</span> <span class="id" type="var">X</span> <span class="id" type="var">a</span>,<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Q</span> [<span class="id" type="var">X</span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>&#x22A2;</span><span style='font-size:90%;'>&gt;</span></span></span></span> <span class="id" type="var">a</span>]<span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">X</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">a</span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Q</span><span style='letter-spacing:-.4em;'>}</span>}.<br/>
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">unfold</span> <span class="id" type="var">hoare_triple</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">Q</span> <span class="id" type="var">X</span> <span class="id" type="var">a</span> <span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">HE</span> <span class="id" type="var">HQ</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">HE</span>. <span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;<span style='font-size:120%;'>&exist;</span>(<span class="id" type="var">X</span> !<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> <span class="id" type="var">aeval</span> <span class="id" type="var">st</span> <span class="id" type="var">a</span> ; <span class="id" type="var">st</span>). <span class="id" type="tactic">split</span>; <span class="id" type="tactic">try</span> <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">assumption</span>. <span class="id" type="keyword">Qed</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">hoare_consequence_pre</span> : <span style='font-size:120%;'>&forall;</span>(<span class="id" type="var">P</span> <span class="id" type="var">P'</span> <span class="id" type="var">Q</span> : <span class="id" type="var">Assertion</span>) <span class="id" type="var">c</span>,<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P'</span><span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">c</span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Q</span><span style='letter-spacing:-.4em;'>}</span>} →<br/>
&nbsp;&nbsp;<span class="id" type="var">P</span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>></span>></span></span> <span class="id" type="var">P'</span> →<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">c</span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Q</span><span style='letter-spacing:-.4em;'>}</span>}.<br/>
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">P</span> <span class="id" type="var">P'</span> <span class="id" type="var">Q</span> <span class="id" type="var">c</span> <span class="id" type="var">Hhoare</span> <span class="id" type="var">Himp</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">Hc</span> <span class="id" type="var">HP</span>. <span class="id" type="tactic">apply</span> (<span class="id" type="var">Hhoare</span> <span class="id" type="var">st</span> <span class="id" type="var">st'</span>).<br/>
&nbsp;&nbsp;<span class="id" type="tactic">assumption</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">Himp</span>. <span class="id" type="tactic">assumption</span>. <span class="id" type="keyword">Qed</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">hoare_consequence_post</span> : <span style='font-size:120%;'>&forall;</span>(<span class="id" type="var">P</span> <span class="id" type="var">Q</span> <span class="id" type="var">Q'</span> : <span class="id" type="var">Assertion</span>) <span class="id" type="var">c</span>,<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">c</span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Q'</span><span style='letter-spacing:-.4em;'>}</span>} →<br/>
&nbsp;&nbsp;<span class="id" type="var">Q'</span> <span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span><span style='letter-spacing:-.2em;'>></span>></span></span> <span class="id" type="var">Q</span> →<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">c</span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Q</span><span style='letter-spacing:-.4em;'>}</span>}.<br/>
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">P</span> <span class="id" type="var">Q</span> <span class="id" type="var">Q'</span> <span class="id" type="var">c</span> <span class="id" type="var">Hhoare</span> <span class="id" type="var">Himp</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">st</span> <span class="id" type="var">r</span> <span class="id" type="var">Hc</span> <span class="id" type="var">HP</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">unfold</span> <span class="id" type="var">hoare_triple</span> <span class="id" type="keyword">in</span> <span class="id" type="var">Hhoare</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">assert</span> (<span style='font-size:120%;'>&exist;</span><span class="id" type="var">st'</span>, <span class="id" type="var">r</span> = <span class="id" type="var">RNormal</span> <span class="id" type="var">st'</span> ∧ <span class="id" type="var">Q'</span> <span class="id" type="var">st'</span>).<br/>
&nbsp;&nbsp;{ <span class="id" type="tactic">apply</span> (<span class="id" type="var">Hhoare</span> <span class="id" type="var">st</span>); <span class="id" type="tactic">assumption</span>. }<br/>
&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> <span class="id" type="var">H</span> <span class="id" type="keyword">as</span> [<span class="id" type="var">st'</span> [<span class="id" type="var">Hr</span> <span class="id" type="var">HQ'</span>]].<br/>
&nbsp;&nbsp;<span style='font-size:120%;'>&exist;</span><span class="id" type="var">st'</span>. <span class="id" type="tactic">split</span>; <span class="id" type="tactic">try</span> <span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">Himp</span>. <span class="id" type="tactic">assumption</span>.<br/>
<span class="id" type="keyword">Qed</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">hoare_seq</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">P</span> <span class="id" type="var">Q</span> <span class="id" type="var">R</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span>,<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Q</span><span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">c<sub>2</sub></span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">R</span><span style='letter-spacing:-.4em;'>}</span>} →<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">c<sub>1</sub></span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Q</span><span style='letter-spacing:-.4em;'>}</span>} →<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">c<sub>1</sub></span>;;<span class="id" type="var">c<sub>2</sub></span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">R</span><span style='letter-spacing:-.4em;'>}</span>}.<br/>
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">P</span> <span class="id" type="var">Q</span> <span class="id" type="var">R</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">H<sub>1</sub></span> <span class="id" type="var">H<sub>2</sub></span> <span class="id" type="var">st</span> <span class="id" type="var">r</span> <span class="id" type="var">H<sub>12</sub></span> <span class="id" type="var">Pre</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">H<sub>12</sub></span>; <span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;- <span class="id" type="tactic">eapply</span> <span class="id" type="var">H<sub>1</sub></span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="id" type="tactic">apply</span> <span class="id" type="var">H<sub>6</sub></span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="id" type="tactic">apply</span> <span class="id" type="var">H<sub>2</sub></span> <span class="id" type="keyword">in</span> <span class="id" type="var">H<sub>3</sub></span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">H<sub>3</sub></span> <span class="id" type="keyword">in</span> <span class="id" type="var">Pre</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> <span class="id" type="var">Pre</span> <span class="id" type="keyword">as</span> [<span class="id" type="var">st'0</span> [<span class="id" type="var">Heq</span> <span class="id" type="var">HQ</span>]].<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">Heq</span>; <span class="id" type="tactic">subst</span>. <span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;找到矛盾的假设&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">H<sub>2</sub></span> <span class="id" type="keyword">in</span> <span class="id" type="var">H<sub>5</sub></span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">H<sub>5</sub></span> <span class="id" type="keyword">in</span> <span class="id" type="var">Pre</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> <span class="id" type="var">Pre</span> <span class="id" type="keyword">as</span> [<span class="id" type="var">st'</span> [<span class="id" type="var">C</span> <span class="id" type="var">_</span>]].<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">C</span>.<br/>
<span class="id" type="keyword">Qed</span>.<br/>
</div>

<div class="doc">
 把你的霍尔规则，<span class="inlinecode"><span class="id" type="var">hoare_assert</span></span> 和 <span class="inlinecode"><span class="id" type="var">hoare_assume</span></span> 写在下面。
</div>
<div class="code code-tight">

<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span><br/>
</div>

<div class="doc">
下列是其它证明规则（用来检查是否合理）
</div>
<div class="code code-tight">
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">hoare_skip</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">P</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">SKIP</span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>}.<br/>
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">P</span> <span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">H</span> <span class="id" type="var">HP</span>. <span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span>. <span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;<span class="id" type="var">eexists</span>. <span class="id" type="tactic">split</span>. <span class="id" type="tactic">reflexivity</span>. <span class="id" type="tactic">assumption</span>.<br/>
<span class="id" type="keyword">Qed</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">hoare_if</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">P</span> <span class="id" type="var">Q</span> <span class="id" type="var">b</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span>,<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">P</span> <span class="id" type="var">st</span> ∧ <span class="id" type="var">bassn</span> <span class="id" type="var">b</span> <span class="id" type="var">st</span><span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">c<sub>1</sub></span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Q</span><span style='letter-spacing:-.4em;'>}</span>} →<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">P</span> <span class="id" type="var">st</span> ∧ ¬(<span class="id" type="var">bassn</span> <span class="id" type="var">b</span> <span class="id" type="var">st</span>)<span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">c<sub>2</sub></span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Q</span><span style='letter-spacing:-.4em;'>}</span>} →<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">TEST</span> <span class="id" type="var">b</span> <span class="id" type="var">THEN</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">ELSE</span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">FI</span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">Q</span><span style='letter-spacing:-.4em;'>}</span>}.<br/>
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">P</span> <span class="id" type="var">Q</span> <span class="id" type="var">b</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">HTrue</span> <span class="id" type="var">HFalse</span> <span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">HE</span> <span class="id" type="var">HP</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">HE</span>; <span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;b&nbsp;是&nbsp;true&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> (<span class="id" type="var">HTrue</span> <span class="id" type="var">st</span> <span class="id" type="var">st'</span>).<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">split</span>. <span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">bexp_eval_true</span>. <span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;b&nbsp;是&nbsp;false&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> (<span class="id" type="var">HFalse</span> <span class="id" type="var">st</span> <span class="id" type="var">st'</span>).<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">split</span>. <span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">bexp_eval_false</span>. <span class="id" type="tactic">assumption</span>. <span class="id" type="keyword">Qed</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">hoare_while</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">P</span> <span class="id" type="var">b</span> <span class="id" type="var">c</span>,<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">P</span> <span class="id" type="var">st</span> ∧ <span class="id" type="var">bassn</span> <span class="id" type="var">b</span> <span class="id" type="var">st</span><span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">c</span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>} →<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="var">P</span><span style='letter-spacing:-.4em;'>}</span>} <span class="id" type="var">WHILE</span> <span class="id" type="var">b</span> <span class="id" type="var">DO</span> <span class="id" type="var">c</span> <span class="id" type="var">END</span> <span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">P</span> <span class="id" type="var">st</span> ∧ ¬(<span class="id" type="var">bassn</span> <span class="id" type="var">b</span> <span class="id" type="var">st</span>)<span style='letter-spacing:-.4em;'>}</span>}.<br/>
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">P</span> <span class="id" type="var">b</span> <span class="id" type="var">c</span> <span class="id" type="var">Hhoare</span> <span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">He</span> <span class="id" type="var">HP</span>.<br/>
&nbsp;&nbsp;<span class="id" type="var">remember</span> (<span class="id" type="var">WHILE</span> <span class="id" type="var">b</span> <span class="id" type="var">DO</span> <span class="id" type="var">c</span> <span class="id" type="var">END</span>) <span class="id" type="keyword">as</span> <span class="id" type="var">wcom</span> <span class="id" type="var">eqn</span>:<span class="id" type="var">Heqwcom</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">induction</span> <span class="id" type="var">He</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">try</span> (<span class="id" type="tactic">inversion</span> <span class="id" type="var">Heqwcom</span>); <span class="id" type="tactic">subst</span>; <span class="id" type="tactic">clear</span> <span class="id" type="var">Heqwcom</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;E_WhileFalse&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">eexists</span>. <span class="id" type="tactic">split</span>. <span class="id" type="tactic">reflexivity</span>. <span class="id" type="tactic">split</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">assumption</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">bexp_eval_false</span>. <span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;E_WhileTrueNormal&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">clear</span> <span class="id" type="var">IHHe1</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">IHHe2</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">clear</span> <span class="id" type="var">IHHe2</span> <span class="id" type="var">He<sub>2</sub></span> <span class="id" type="var">r</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">unfold</span> <span class="id" type="var">hoare_triple</span> <span class="id" type="keyword">in</span> <span class="id" type="var">Hhoare</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">Hhoare</span> <span class="id" type="keyword">in</span> <span class="id" type="var">He<sub>1</sub></span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="id" type="tactic">destruct</span> <span class="id" type="var">He<sub>1</sub></span> <span class="id" type="keyword">as</span> [<span class="id" type="var">st<sub>1</sub></span> [<span class="id" type="var">Heq</span> <span class="id" type="var">Hst1</span>]].<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">Heq</span>; <span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="id" type="tactic">split</span>; <span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;E_WhileTrueError&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">exfalso</span>. <span class="id" type="tactic">clear</span> <span class="id" type="var">IHHe</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">unfold</span> <span class="id" type="var">hoare_triple</span> <span class="id" type="keyword">in</span> <span class="id" type="var">Hhoare</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">Hhoare</span> <span class="id" type="keyword">in</span> <span class="id" type="var">He</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="id" type="tactic">destruct</span> <span class="id" type="var">He</span> <span class="id" type="keyword">as</span> [<span class="id" type="var">st'</span> [<span class="id" type="var">C</span> <span class="id" type="var">_</span>]]. <span class="id" type="tactic">inversion</span> <span class="id" type="var">C</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="id" type="tactic">split</span>; <span class="id" type="tactic">assumption</span>.<br/>
<span class="id" type="keyword">Qed</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Example</span> <span class="id" type="var">assert_assume_example</span>:<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">True</span><span style='letter-spacing:-.4em;'>}</span>}<br/>
&nbsp;&nbsp;<span class="id" type="var">ASSUME</span> (<span class="id" type="var">X</span> = 1);;<br/>
&nbsp;&nbsp;<span class="id" type="var">X</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">X</span> + 1;;<br/>
&nbsp;&nbsp;<span class="id" type="var">ASSERT</span> (<span class="id" type="var">X</span> = 2)<br/>
&nbsp;&nbsp;<span style='letter-spacing:-.4em;'>{</span>{<span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">True</span><span style='letter-spacing:-.4em;'>}</span>}.<br/>
<span class="id" type="keyword">Proof</span>.<br/>
<span class="comment">(*&nbsp;请在此处解答&nbsp;*)</span> <span class="id" type="var">Admitted</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">End</span> <span class="id" type="var">HoareAssertAssume</span>.<br/>
</div>

<span class="proofbox">&#9744;</span> 
<div class="code code-tight">

<span class="comment">(*&nbsp;Mon&nbsp;Oct&nbsp;28&nbsp;08:15:17&nbsp;UTC&nbsp;2019&nbsp;*)</span><br/>
</div>
</div>



</div>

</body>
</html>